├── .classpath
├── .gitignore
├── .project
├── .settings
└── org.eclipse.jdt.core.prefs
├── README.md
└── src
├── Main.java
├── Smali
├── SmaliClass.java
├── SmaliField.java
├── SmaliMethod.java
├── SmaliModifier.java
└── SmaliObject.java
└── Utils.java
/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /bin/
2 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | ObfuseRestore
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 |
15 | org.eclipse.jdt.core.javanature
16 |
17 |
18 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.jdt.core.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
4 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
5 | org.eclipse.jdt.core.compiler.compliance=1.8
6 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate
7 | org.eclipse.jdt.core.compiler.debug.localVariable=generate
8 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate
9 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
10 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
11 | org.eclipse.jdt.core.compiler.source=1.8
12 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 字符串解密
2 |
3 | 适用加密方法单String参数,返回类型为String。
4 |
5 | 有的字符串不能处理是因为编码坑爹。。
6 |
7 | ubuntu下测试正常,其余未测。
8 |
9 | **注:使用baksmali d 和smali a,不要使用dex2jar里的smali和baksmali。**
10 |
11 | use:
12 |
13 | java -jar restore.jar \ \ \
14 |
15 | 例:
16 | java -jar restore.jar classes-dex2jar.jar out Lcom/inca/security/coM6;->goto
17 |
--------------------------------------------------------------------------------
/src/Main.java:
--------------------------------------------------------------------------------
1 | import java.io.File;
2 | import java.lang.reflect.InvocationTargetException;
3 | import java.lang.reflect.Method;
4 | import java.net.MalformedURLException;
5 | import java.net.URL;
6 | import java.net.URLClassLoader;
7 | import java.util.ArrayList;
8 | import java.util.regex.Matcher;
9 | import java.util.regex.Pattern;
10 |
11 | import Smali.SmaliClass;
12 | import Smali.SmaliMethod;
13 | import Smali.SmaliModifier.ModifierAttribute;
14 | import Smali.SmaliModifier.ModifierPremission;
15 | public class Main {
16 | public static String jar;
17 | public static String smaliDir;
18 | public static String enMtdSig;
19 |
20 | public static URLClassLoader clsLoader;
21 | public static Class deCls;
22 | public static Method deMtd;
23 | public static int num;
24 |
25 | public static void main(String args[]) throws Exception{
26 | jar = args[0];
27 | smaliDir = args[1];
28 | enMtdSig = args[2];
29 |
30 | Pattern sigPtn = Pattern.compile("L([a-zA-Z0-9/$_]{1,128});->([a-zA-Z0-9/$_]{1,128})");
31 | Matcher mtc = sigPtn.matcher(enMtdSig);
32 | if(!mtc.find()){
33 | System.out.println("not matche methodSig");
34 | return;
35 | }
36 | String className = mtc.group(1).replace("/", ".");
37 | String mtdName = mtc.group(2);
38 | URLClassLoader clsLoader = new URLClassLoader(new URL[]{new File(jar).toURI().toURL()});
39 | Class deCls = clsLoader.loadClass(className);
40 | deMtd = deCls.getMethod(mtdName, String.class);
41 | ArrayList files = Utils.GetInDirFiles(new File(smaliDir));
42 | for(File file : files){
43 | SmaliClass cls = SmaliClass.PraseClass(file);
44 | restore(cls);
45 | }
46 | System.out.println("restored, restore num is " + num);
47 | // if(args[0].equals("-p")){
48 | // if(args.length>= 4 && args[2].equals("--f")){
49 | // SafeProject(new File(args[1]),args[3]);
50 | // }
51 | // else{
52 | // SafeProject(new File(args[1]),null);
53 | // }
54 | // }
55 | //
56 |
57 | }
58 |
59 |
60 | public static void restore(SmaliClass cls) throws Exception{
61 | ArrayList codes = cls.getCodes();
62 |
63 |
64 |
65 | Pattern invokePtn = Pattern.compile("invoke-static \\{([vp\\d]{0,4})\\}, "+enMtdSig);
66 | for(int i = 0;i " + deText);
100 | num++;
101 | }
102 | }
103 | cls.saveChange();
104 | }
105 |
106 |
107 | // public static void restore(File dex,String methidSig){
108 | // File maniFile = new File(projectDir.toString() + "\\AndroidManifest.xml");
109 | // if(!maniFile.exists()){
110 | // System.out.println("[*SafeProjectError]AndroidManifest.xml is not found");
111 | // return;
112 | // }
113 | // String mainClassName = Utils.FindMainClass(maniFile);
114 | // if(mainClassName == null){
115 | // System.out.println("[*SafeProjectError]Launcher Class is not found");
116 | // return;
117 | // }
118 | // ArrayList files = Utils.GetInDirFiles(new File(projectDir.toString() +"\\smali\\"));
119 | // if(files == null){
120 | // System.out.println("[*SafeProjectError]Files is null");
121 | // return;
122 | // }
123 | // for(File file : files){
124 | // SmaliClass cls = SmaliUtils.PraseClass(file);
125 | // if(cls == null || cls.isAbstract() || cls.isInterface() || cls.toString().indexOf("$") != -1){
126 | // continue;
127 | // }
128 | // if(cls.toString().startsWith("Landroid")){
129 | // continue;
130 | // }
131 | // String className = cls.toString();
132 | // className = className.startsWith("L") ? className.substring(1,className.length()-1) : className;
133 | // className = className.endsWith(";") ? className.substring(0,className.length()-1) : className;
134 | // className = className.replace("/",".");
135 | // if(filter != null){
136 | // if(className.indexOf(filter) == -1){
137 | // if(mainClassName.equals(className)){
138 | // SmaliClass.ClassTable.add(cls);
139 | // AddClinit(cls);
140 | // cls.saveChange();
141 | // }
142 | // continue;
143 | // }
144 | // }
145 | // SmaliClass.ClassTable.add(cls);
146 | // System.out.println("[I:ChangeSmali]: " + cls.toString());
147 | // ChangeSmali(cls);
148 | // if(mainClassName.equals(className)){
149 | // AddClinit(cls);
150 | // }
151 | // cls.saveChange();
152 | // }
153 | // NativeHelper helper = NativeHelper.getInstance();
154 | // helper.setOnLoadCode(helper.createOnLoadCode());
155 | // helper.writeSource();
156 | // }
157 | //
158 | // public static void ChangeSmali(SmaliClass cls){
159 | // String methodArrayName = Utils.GetRandomMethodName(0); //�������
160 | // NativeHelper helper = NativeHelper.getInstance();
161 | // NativeArray array = new NativeArray(cls.toString(),methodArrayName);
162 | // ArrayList smaliMethods = cls.getMethods();
163 | // ArrayList addMethod = new ArrayList();
164 | // for(int i = 0 ;i < smaliMethods.size() ; i++){
165 | // SmaliMethod method = smaliMethods.get(i);
166 | // String srcName = method.getMethodName();
167 | // if(method.isNative() || method.isSynthetic() || method.isFinal()){
168 | // continue;
169 | // }
170 | // //�����������;�̬�����
171 | // if(!"".equals(srcName) && !"".equals(srcName) ){
172 | // String reName = Utils.GetRandomMethodName(1); //�������
173 | // method.rename(reName);
174 | // NativeMethod nativeMethod = NativeMethod.smaliMethod2NativeMethod(method,Utils.GetRandomMethodName(2)); //nativeName�������
175 | // helper.addMethod(nativeMethod);
176 | // array.add(new JNINativeMethod(srcName,method.getMethodSig().toString(),NativeHelper.SmaliType2NativeType(method.getReturnTypeName()),nativeMethod.getMethodName()));
177 | // ArrayList attributes = method.getAttributes();
178 | // attributes.add(ModifierAttribute.ATTRIBUTE_NATIVE);
179 | // addMethod.add(new SmaliMethod(method.getPremission(),attributes,method.getArgs(),method.getReturnTypeName(),method.getSuperClassName(),srcName,-1));
180 | // }
181 | // }
182 | // for(SmaliMethod method : addMethod){
183 | // cls.addMethod(method, "");
184 | // }
185 | // helper.addJNIMethod(array);
186 | // }
187 | //
188 | // public static void AddClinit(SmaliClass cls){
189 | // ArrayList attr = new ArrayList();
190 | // attr.add(ModifierAttribute.ATTRIBUTE_STATIC);
191 | // attr.add(ModifierAttribute.ATTRIBUTE_CONSTRUCTOR);
192 | // SmaliMethod clinit = new SmaliMethod(ModifierPremission.PREMISSION_DEFAULT,attr,new ArrayList(),"V",cls.toString(),"",-1);
193 | // StringBuilder codes = new StringBuilder();
194 | // if(cls.findMethod(clinit) == null){
195 | // codes.append(" .locals 1\r\n");
196 | // codes.append(" const-string v0,\"smalisafe\"\r\n");
197 | // codes.append(" invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V\r\n");
198 | // codes.append(" return-void\r\n");
199 | // cls.addMethod(clinit, codes.toString());
200 | // }
201 | // else{
202 | // clinit = cls.findMethod(clinit);
203 | // clinit.addLineCodeToEnd(" const-string v0,\"smalisafe\"");
204 | // clinit.addLineCodeToEnd(" invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V");
205 | // }
206 | // }
207 | }
208 |
--------------------------------------------------------------------------------
/src/Smali/SmaliClass.java:
--------------------------------------------------------------------------------
1 | package Smali;
2 | import java.io.BufferedReader;
3 | import java.io.BufferedWriter;
4 | import java.io.File;
5 | import java.io.FileNotFoundException;
6 | import java.io.FileReader;
7 | import java.io.FileWriter;
8 | import java.io.IOException;
9 | import java.util.ArrayList;
10 | import java.util.regex.Matcher;
11 | import java.util.regex.Pattern;
12 |
13 | import Smali.SmaliClass.SmaliType;
14 | import Smali.SmaliModifier.ModifierAttribute;
15 | import Smali.SmaliModifier.ModifierPremission;
16 | import Smali.SmaliModifier.ModifierType;
17 |
18 | public class SmaliClass extends SmaliObject{
19 | private final String ClassName;
20 | private final ArrayList fields;
21 | private final ArrayList methods;
22 | private File classFile;
23 | private BufferedReader reader;
24 | private BufferedWriter writer;
25 | private ArrayList codeLines;
26 |
27 | private static final ArrayList ClassTable = new ArrayList();
28 |
29 | public static class SmaliType extends SmaliClass{
30 | private boolean isArr;
31 | private int arrNum;
32 |
33 |
34 | public SmaliType(ModifierPremission premission,ArrayList attributes,ArrayList fields,ArrayList methods,String name,boolean isArr,int arrNum){
35 | super(premission,attributes,fields,methods,name,null);
36 | this.isArr = isArr;
37 | this.arrNum = arrNum;
38 | }
39 |
40 | public boolean isArr() {
41 | return isArr;
42 | }
43 |
44 | public void setArr(boolean isArr) {
45 | this.isArr = isArr;
46 | }
47 |
48 | public int getArrNum() {
49 | return arrNum;
50 | }
51 |
52 | public void setArrNum(int arrNum) {
53 | this.arrNum = arrNum;
54 | }
55 |
56 |
57 | public static final SmaliType V = new SmaliType(ModifierPremission.PREMISSION_PUBLIC,null,null,null,"V",false,0);
58 | public static final SmaliType Z = new SmaliType(ModifierPremission.PREMISSION_PUBLIC,null,null,null,"Z",false,0);
59 | public static final SmaliType I = new SmaliType(ModifierPremission.PREMISSION_PUBLIC,null,null,null,"I",false,0);
60 | public static final SmaliType B = new SmaliType(ModifierPremission.PREMISSION_PUBLIC,null,null,null,"B",false,0);
61 | public static final SmaliType S = new SmaliType(ModifierPremission.PREMISSION_PUBLIC,null,null,null,"S",false,0);
62 | public static final SmaliType C = new SmaliType(ModifierPremission.PREMISSION_PUBLIC,null,null,null,"C",false,0);
63 | public static final SmaliType J = new SmaliType(ModifierPremission.PREMISSION_PUBLIC,null,null,null,"J",false,0);
64 | public static final SmaliType F = new SmaliType(ModifierPremission.PREMISSION_PUBLIC,null,null,null,"F",false,0);
65 | public static final SmaliType D = new SmaliType(ModifierPremission.PREMISSION_PUBLIC,null,null,null,"D",false,0);
66 |
67 | public char getChar(){
68 | return toString().charAt(0);
69 | }
70 |
71 | public static SmaliType GetBaseType(char c){
72 | if(c == V.getChar()){
73 | return V;
74 | }
75 | else if(c == Z.getChar()){
76 | return Z;
77 | }
78 | else if(c == I.getChar()){
79 | return I;
80 | }
81 | else if(c == B.getChar()){
82 | return B;
83 | }
84 | else if(c == S.getChar()){
85 | return S;
86 | }
87 | else if(c == C.getChar()){
88 | return C;
89 | }
90 | else if(c == J.getChar()){
91 | return J;
92 | }
93 | else if(c == F.getChar()){
94 | return F;
95 | }
96 | else if(c == D.getChar()){
97 | return D;
98 | }
99 | else{
100 | return null;
101 | }
102 | }
103 | }
104 |
105 | private SmaliClass(ModifierPremission premission,ArrayList attributes,ArrayList fields,ArrayList methods,String name,File classFile){
106 | super(premission,attributes,0);
107 | this.ClassName = name;
108 | this.fields = fields;
109 | this.methods = methods;
110 | this.classFile = classFile;
111 | }
112 |
113 | public static SmaliClass PraseClass(File file){
114 | BufferedReader reader;
115 | try {
116 | reader = new BufferedReader(new FileReader(file));
117 | } catch (FileNotFoundException e) {
118 | System.out.println("[*PraseClassError]FileNotFoundException: " + e.toString());
119 | return null;
120 | }
121 | String line;
122 | String className = "";
123 | int lineInFile = 0;
124 | ModifierPremission premission = ModifierPremission.PREMISSION_DEFAULT;
125 | ArrayList attributes = new ArrayList();
126 | ArrayList fields = new ArrayList();
127 | ArrayList methods = new ArrayList();
128 | try {
129 | while((line = reader.readLine()) != null){
130 | line = line.trim();
131 | if(line.startsWith(ModifierType.TYPE_CLASS.toString())){
132 | String[] sp = line.split(" "); //sp[] = {".class",Premission,{Attributes},ClassName}
133 | premission = ModifierPremission.Get(sp[1]);
134 | for(int i = 2;i < sp.length - 1;i++){
135 | attributes.add(ModifierAttribute.Get(sp[i]));
136 | }
137 | className = sp[sp.length-1];
138 | }
139 | /*
140 | if(line.startsWith(SmaliModifier.ModifierType.TYPE_FIELD.getModifierText())){
141 | String[] sp = line.split(" ");
142 | SmaliModifier.ModifierPremission fieldPremission = SmaliModifier.ModifierPremission.Get(sp[0]);
143 | ArrayList fieldAttributes = new ArrayList();
144 | for(int i = 2;i < sp.length - 1 ;i++){
145 | fieldAttributes.add(SmaliModifier.ModifierAttribute.Get(sp[i]));
146 | }
147 | String sp1[] = sp[sp.length-1].split(":");
148 | SmaliField field = new SmaliField();
149 | }*/
150 |
151 | if(line.startsWith(ModifierType.TYPE_METHOD.toString())){
152 | String[] sp = line.split(" "); //sp[] = {".method",Premission,{Attributes},MethodName+MethodSig}
153 | ModifierPremission methodPremission= ModifierPremission.Get(sp[1]);
154 | ArrayList methodAttributes = new ArrayList();
155 | for(int i = 2;i < sp.length - 1 ;i++){
156 | methodAttributes.add(ModifierAttribute.Get(sp[i]));
157 | }
158 | String[] sp1 = sp[sp.length-1].split("\\(");
159 | String methodName = sp1[0];
160 | ArrayList args = SmaliMethod.PraseMethodArgs(sp1[1].split("\\)")[0]);
161 | String returnType = sp1[1].split("\\)")[1];
162 | SmaliMethod method = new SmaliMethod(methodPremission,methodAttributes,args,returnType,className,methodName,lineInFile);
163 | methods.add(method);
164 | }
165 | lineInFile++;
166 | }
167 | reader.close();
168 | SmaliClass cls = new SmaliClass(premission,attributes,fields,methods,className,file);
169 | SmaliClass.ClassTable.add(cls);
170 | return cls;
171 | } catch (IOException e) {
172 | System.out.println("[*PraseClassError]IOException: " + e.toString());
173 | return null;
174 | }
175 | }
176 |
177 | public String toString(){
178 | return ClassName;
179 | }
180 |
181 | public boolean equals(SmaliClass cls){
182 | if(cls == null){
183 | return false;
184 | }
185 | return cls.toString() == this.toString();
186 | }
187 |
188 | public ArrayList getFields(){
189 | return fields;
190 | }
191 |
192 | public BufferedWriter getWriter(){
193 | if(writer == null){
194 | if(classFile == null){
195 | return null;
196 | }
197 | try {
198 | writer = new BufferedWriter(new FileWriter(classFile));
199 | } catch (IOException e) {
200 | System.out.println("[*E] FileNotFound:" + e.toString());
201 | }
202 | }
203 | return writer;
204 | }
205 |
206 | public ArrayList getCodes(){
207 | if(codeLines == null){
208 | if(reader == null ){
209 | if(classFile == null){
210 | return null;
211 | }
212 | try {
213 | reader = new BufferedReader(new FileReader(classFile));
214 | } catch (FileNotFoundException e) {
215 | System.out.println("[*GetCodesError] FileNotFound: " + e.toString());
216 | return null;
217 | }
218 | }
219 | ArrayList codes = new ArrayList();
220 | String tmp;
221 | try {
222 | while((tmp = reader.readLine()) != null){
223 | codes.add(tmp);
224 | }
225 | reader.close();
226 | } catch (IOException e) {
227 | System.out.println("[*GetCodesError] IOExceotion: " + e.toString());
228 | return null;
229 | }
230 |
231 | codeLines = codes;
232 | }
233 | return codeLines;
234 | }
235 |
236 | public ArrayList getMethods(){
237 | return methods;
238 | }
239 |
240 | public File getClassFile(){
241 | return classFile;
242 | }
243 |
244 | public ArrayList getInvokeMethodList(){
245 | ArrayList list = new ArrayList();
246 | for(String line : getCodes()){
247 | line = line.trim();
248 | String[] sp = line.split(" ");
249 | if(sp[0].indexOf("invoke") != -1){
250 | Pattern pattern = Pattern.compile("([a-zA-Z0-9/_$]{0,128});->([0-9a-zA-Z_$]{0,128})\\(([a-zA-Z0-9/_$;]{0,512})\\)([a-zA-Z0-9/_$;]{0,128})");
251 | Matcher matcher = pattern.matcher(line);
252 | if(matcher.find()){
253 | String superClass = matcher.group(1);
254 | String returnType;
255 | SmaliMethod method;
256 | ArrayList args = SmaliMethod.PraseMethodArgs(matcher.group(3));
257 | returnType = matcher.group(4);
258 | method = new SmaliMethod(ModifierPremission.PREMISSION_DEFAULT,null,args,returnType,superClass,matcher.group(2),-1);
259 | list.add(method);
260 | }
261 | }
262 | }
263 | return list;
264 | }
265 |
266 | public int addMethod(SmaliMethod method,String smaliCode){
267 | if(method == null){
268 | return -1;
269 | }
270 | method.setLineInFile(getCodes().size()+2);
271 | StringBuilder builder = new StringBuilder();
272 | ArrayList codeLines = getCodes();
273 | codeLines.add("");
274 | builder.append(SmaliModifier.ModifierType.TYPE_METHOD+" ");
275 | builder.append(method.getPremission().toString()+" ");
276 | if(method.getAttributes() != null && method.getAttributes().size() != 0){
277 | for(SmaliModifier modifier : method.getAttributes()){
278 | builder.append(modifier + " ");
279 | }
280 | }
281 | builder.append(method.getMethodName()+"(");
282 | if(method.getArgs() != null){
283 | for(String type : method.getArgs()){
284 | builder.append(type.toString());
285 | }
286 | }
287 | builder.append(")");
288 | builder.append(method.getReturnTypeName());
289 | codeLines.add(builder.toString());
290 | String[] smaliLines = smaliCode.split("\r\n");
291 | for(String line : smaliLines){
292 | codeLines.add(line);
293 | }
294 | codeLines.add(".end method");
295 | this.codeLines = codeLines;
296 | method.setSuperClass(this.toString());
297 | methods.add(method);
298 |
299 | return 0;
300 |
301 | }
302 |
303 | public int saveChange(){
304 | try {
305 | if(writer != null){
306 | writer.close();
307 | writer = null;
308 | }
309 | if(this.codeLines == null){
310 | return 0;
311 | }
312 | writer = getWriter();
313 | for(String tmp : getCodes()){
314 | writer.write(tmp+"\r\n");
315 | }
316 | writer.flush();
317 | cleanMem();
318 | return 0;
319 | } catch (IOException e) {
320 | System.out.println("[*SaveChangeError: ]" +e.toString());
321 | return -1;
322 | }
323 | }
324 |
325 | public void cleanMem(){
326 | if(reader != null){
327 | try {
328 | reader.close();
329 | } catch (IOException e) {
330 | }
331 | }
332 | if(writer != null){
333 | try {
334 | writer.close();
335 | } catch (IOException e) {
336 | }
337 |
338 | }
339 | codeLines = null;
340 | reader = null;
341 | writer = null;
342 | }
343 |
344 | public SmaliMethod findMethod(SmaliMethod method){
345 | for(SmaliMethod m : methods){
346 | if(m.equals(method)){
347 | return m;
348 | }
349 | }
350 | return null;
351 | }
352 |
353 | public static SmaliClass FindClass(String cls){
354 | if(cls == null || cls.isEmpty()){
355 | return null;
356 | }
357 | if(cls.length() == 1 ){
358 | return SmaliType.GetBaseType(cls.charAt(0));
359 | }
360 | for(SmaliClass sc : ClassTable){
361 | if(sc.equals(cls)){
362 | return sc;
363 | }
364 | }
365 | return null;
366 | }
367 |
368 | public boolean isInterface(){
369 | if(getAttributes().indexOf(ModifierAttribute.ATTRIBUTE_INTERFACE) != -1){
370 | return true;
371 | }
372 | return false;
373 | }
374 |
375 | public boolean isAbstract(){
376 | if(getAttributes().indexOf(ModifierAttribute.ATTRIBUTE_ABSTRACT) != -1){
377 | return true;
378 | }
379 | return false;
380 | }
381 |
382 | public boolean equals(Object cls){
383 | return cls.toString().equals(this.toString());
384 | }
385 | }
386 |
--------------------------------------------------------------------------------
/src/Smali/SmaliField.java:
--------------------------------------------------------------------------------
1 | package Smali;
2 | import java.util.ArrayList;
3 |
4 | import Smali.SmaliModifier.ModifierAttribute;
5 | import Smali.SmaliModifier.ModifierPremission;
6 |
7 | public class SmaliField extends SmaliObject{
8 | private final String type;
9 | private final String fieldName;
10 |
11 | public SmaliField(ModifierPremission premission,ArrayList attributes,String type,String name,int lineInFile){
12 | super(premission,attributes,lineInFile);
13 | this.type = type;
14 | this.fieldName = name;
15 | }
16 |
17 | public String toString(){
18 | return fieldName;
19 | }
20 |
21 | public String getName(){
22 | return fieldName;
23 | }
24 |
25 | public SmaliClass getType(){
26 | return SmaliClass.FindClass(type);
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/src/Smali/SmaliMethod.java:
--------------------------------------------------------------------------------
1 | package Smali;
2 | import java.util.ArrayList;
3 | import java.util.regex.Matcher;
4 | import java.util.regex.Pattern;
5 |
6 | import Smali.SmaliClass.SmaliType;
7 | import Smali.SmaliModifier.ModifierAttribute;
8 | import Smali.SmaliModifier.ModifierPremission;
9 | import Smali.SmaliModifier.ModifierType;
10 |
11 | public class SmaliMethod extends SmaliObject{
12 | private String methodName;
13 | private ArrayList args;
14 | private String superClass;
15 | private String returnType;
16 |
17 | public static final String MethodRegEx = ModifierType.TYPE_METHOD +" ([a-z ]{0,64}) ([a-zA-Z0-9_$<>]{0,128})\\(([a-zA-Z0-9_$;/\\[]{0,512})\\)([a-zA-Z0-9_$;/\\[]{0,256})";
18 | public static final String MethodRegEx_NotPre = ModifierType.TYPE_METHOD +" ([a-zA-Z0-9_$<>]{0,128})\\(([a-zA-Z0-9_$;\\[/]{0,512})\\)([a-zA-Z0-9_$;/\\[]{0,256})";
19 |
20 |
21 |
22 | /**
23 | * @param premission: ModifierPremission
24 | * **/
25 | public SmaliMethod(ModifierPremission premission,ArrayList attributes,ArrayList args,String returnType,String superCls,String name,int lineInFile){
26 | super(premission,attributes,lineInFile);
27 | this.args = args;
28 | this.returnType = returnType;
29 | this.methodName = name;
30 | this.superClass = superCls;
31 | }
32 |
33 | public SmaliMethod(String name,ArrayList args,String returnType){
34 | this(null,null,args,returnType,null,name,-1);
35 | }
36 |
37 | /**
38 | * @return ClassName+"->"+MethodName
39 | * **/
40 | public String toString(){
41 | return superClass+"->"+methodName;
42 | }
43 |
44 | public boolean equals(SmaliMethod method){
45 | if(method == null){
46 | return false;
47 | }
48 | if(!this.methodName.equals(method.methodName)){
49 | return false;
50 | }
51 | if(!this.getMethodSig().equals(method.getMethodSig())){
52 | return false;
53 | }
54 | return true;
55 | }
56 |
57 | private void setMethodName(String name){
58 | this.methodName = name;
59 | }
60 |
61 | public void setSuperClass(String clsName){
62 | this.superClass = clsName;
63 | }
64 |
65 | public boolean isSynthetic(){
66 | if(getAttributes().indexOf(ModifierAttribute.ATTRIBUTE_SYNTHETIC) == -1 && getAttributes().indexOf(ModifierAttribute.ATTRIBUTE_DECLARED_SYNCHRONIZED) == -1){
67 | return false;
68 | }
69 | return true;
70 | }
71 |
72 | public boolean isNative(){
73 | if(getAttributes().indexOf(ModifierAttribute.ATTRIBUTE_NATIVE) != -1){
74 | return true;
75 | }
76 | return false;
77 | }
78 |
79 | public String getMethodName(){
80 | return methodName;
81 | }
82 |
83 | public ArrayList getArgs(){
84 | return args;
85 | }
86 |
87 | public String getMethodSig(){
88 | StringBuilder sig = new StringBuilder("(");
89 | for(String arg : args){
90 | sig.append(arg);
91 | }
92 | sig.append(")");
93 | sig.append(returnType);
94 | return sig.toString();
95 | }
96 |
97 | public SmaliClass getReturnType(){
98 | return SmaliClass.FindClass(returnType);
99 | }
100 |
101 | public SmaliClass getSuperClass(){
102 | return SmaliClass.FindClass(superClass);
103 | }
104 |
105 | public String getReturnTypeName(){
106 | return returnType;
107 | }
108 |
109 | public String getSuperClassName(){
110 | return superClass;
111 | }
112 |
113 | public int rename(String text){
114 | ArrayList codes = getSuperClass().getCodes();
115 | String line = codes.get(getLineInFile()).toString();
116 | if(line == null){
117 | return -1;
118 | }
119 | boolean havePre = true;
120 | Pattern pattern = Pattern.compile(MethodRegEx);
121 | Matcher matcher = pattern.matcher(line);
122 | if(!matcher.find()){
123 | pattern = Pattern.compile(MethodRegEx_NotPre);
124 | matcher = pattern.matcher(line);
125 | if(!matcher.find()){
126 | return -2;
127 | }
128 | havePre = false;
129 | }
130 | if(havePre){
131 | codes.set(getLineInFile(),SmaliModifier.ModifierType.TYPE_METHOD +" " + matcher.group(1) + " " + text + "(" + matcher.group(3) + ")" +matcher.group(4)) ;
132 | }
133 | else{
134 | codes.set(getLineInFile(),SmaliModifier.ModifierType.TYPE_METHOD+" " + text + "(" + matcher.group(2) + ")" +matcher.group(3));
135 | }
136 | setMethodName(text);
137 | return 0;
138 | }
139 |
140 | public void addLineCodeToEnd(String code){
141 | int startLine = getLineInFile();
142 | ArrayList codes = getSuperClass().getCodes();
143 | while(!codes.get(startLine + 1).equals(ModifierType.TYPE_METHOD_END.toString())){
144 | startLine++;
145 | }
146 | codes.add(startLine,code);
147 | setOverAddLine(startLine);
148 | }
149 |
150 | public static ArrayList PraseMethodArgs(String text){
151 | char[] c = text.toCharArray();
152 | ArrayList args = new ArrayList();
153 | int fristi = 0;
154 | int endi = 0;
155 | for(int i = 0;i attributes = new ArrayList();
12 | private int lineInFile;
13 | private int overAddLine = 0;
14 | public int lineOffset = 0;
15 |
16 |
17 | public SmaliObject(ModifierPremission premission,ArrayList attributes,int lineInFile){
18 | this.lineInFile = lineInFile;
19 | if(premission != null){
20 | this.premission = premission;
21 | }
22 | else{
23 | this.premission = ModifierPremission.PREMISSION_DEFAULT;
24 | }
25 | if(attributes == null){
26 | return;
27 | }
28 | for(ModifierAttribute attribute : attributes){
29 | this.attributes.add(attribute);
30 | }
31 | }
32 |
33 | public ModifierPremission getPremission(){
34 | return premission;
35 | }
36 |
37 | public int getOverAddLine() {
38 | return overAddLine;
39 | }
40 |
41 | public void setOverAddLine(int overAddLine) {
42 | this.overAddLine = overAddLine;
43 | }
44 |
45 | public int getLineInFile(){
46 | if(lineInFile > overAddLine){
47 | return lineInFile + lineOffset;
48 | }
49 | return lineInFile;
50 | }
51 |
52 | public void setLineInFile(int line){
53 | this.lineInFile = line;
54 | }
55 |
56 | public ArrayList getAttributes(){
57 | return attributes;
58 | }
59 |
60 | public boolean isStatic(){
61 | if(getAttributes().indexOf(ModifierAttribute.ATTRIBUTE_STATIC) != -1){
62 | return true;
63 | }
64 | return false;
65 | }
66 |
67 | public boolean isFinal(){
68 | if(getAttributes().indexOf(ModifierAttribute.ATTRIBUTE_FINAL) != -1){
69 | return true;
70 | }
71 | return false;
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/Utils.java:
--------------------------------------------------------------------------------
1 | import java.io.BufferedReader;
2 | import java.io.File;
3 | import java.io.FileNotFoundException;
4 | import java.io.FileReader;
5 | import java.io.IOException;
6 | import java.util.ArrayList;
7 | import java.util.Random;
8 | import java.util.regex.Matcher;
9 | import java.util.regex.Pattern;
10 |
11 | public class Utils {
12 | public static String gbEncoding(final String gbString) { //gbString = "测试"
13 | char[] utfBytes = gbString.toCharArray(); //utfBytes = [测, 试]
14 | String unicodeBytes = "";
15 | for (int byteIndex = 0; byteIndex < utfBytes.length; byteIndex++) {
16 | String hexB = Integer.toHexString(utfBytes[byteIndex]); //转换为16进制整型字符串
17 | if (hexB.length() <= 2) {
18 | while(hexB.length() != 4){
19 | hexB = "0" + hexB;
20 | }
21 | }
22 | unicodeBytes = unicodeBytes + "\\u" + hexB;
23 | }
24 | return unicodeBytes;
25 | }
26 | public static ArrayList GetInDirFiles(File dir){
27 | ArrayList fileList = new ArrayList();
28 | if(!dir.isDirectory()){
29 | return fileList;
30 | }
31 | File[] list = dir.listFiles();
32 | if(list == null){
33 | return fileList;
34 | }
35 | for(File file : list){
36 | if(file.isDirectory()){
37 | fileList.addAll(GetInDirFiles(file));
38 | }
39 | else{
40 | fileList.add(file);
41 | }
42 | }
43 | return fileList;
44 | }
45 | }
46 |
--------------------------------------------------------------------------------