· 6 years ago · Nov 07, 2019, 12:42 PM
1package com.example.cipher;
2
3
4import com.github.javaparser.JavaParser;
5import com.github.javaparser.ParseResult;
6import com.github.javaparser.ast.CompilationUnit;
7import com.github.javaparser.ast.NodeList;
8import com.github.javaparser.ast.body.FieldDeclaration;
9import com.github.javaparser.ast.body.VariableDeclarator;
10import com.github.javaparser.ast.expr.ArrayInitializerExpr;
11import com.github.javaparser.ast.expr.AssignExpr;
12import com.github.javaparser.ast.expr.Expression;
13import com.github.javaparser.ast.expr.MethodCallExpr;
14import com.github.javaparser.ast.expr.StringLiteralExpr;
15import com.github.javaparser.utils.Pair;
16
17import java.io.BufferedReader;
18import java.io.File;
19import java.io.FileInputStream;
20import java.io.FileWriter;
21import java.io.IOException;
22import java.io.InputStream;
23import java.io.InputStreamReader;
24import java.nio.file.FileSystems;
25import java.nio.file.FileVisitResult;
26import java.nio.file.FileVisitor;
27import java.nio.file.Files;
28import java.nio.file.Path;
29import java.nio.file.PathMatcher;
30import java.nio.file.StandardCopyOption;
31import java.nio.file.attribute.BasicFileAttributes;
32import java.security.AlgorithmParameters;
33import java.util.ArrayList;
34import java.util.Arrays;
35import java.util.Base64;
36import java.util.HashSet;
37import java.util.Optional;
38import java.util.Random;
39import java.util.Set;
40import java.util.UUID;
41import java.util.concurrent.ThreadLocalRandom;
42import java.util.function.Consumer;
43import java.util.function.Predicate;
44
45import javax.crypto.Cipher;
46import javax.crypto.SecretKey;
47import javax.crypto.SecretKeyFactory;
48import javax.crypto.spec.IvParameterSpec;
49import javax.crypto.spec.PBEKeySpec;
50import javax.crypto.spec.SecretKeySpec;
51
52///home/rokney/AndroidStudioProjects/MyApplication
53public class MyClass {
54 private static String packageName;
55 private static String applicationId;
56 private static String secretPreffix;
57 private static String sha;
58 private static StringBuilder ciphrResultString = new StringBuilder();
59 private static ArrayList<String> targetFiles = null;
60 private static int classCount = 0, stringCount = 0;
61
62 private static String PLACEHOLDER = "AZAK9yqTDuyBS5Hw<-#->";
63
64 public static final int BUIL_TYPE_1 = 1, BUILD_TYPE_2 = 2, BUILD_TYPE_3 = 3, BUILD_TYPE_4 = 4;
65
66 private static Set<String> names = new HashSet<>();
67 private static GenerateJavaClass javaGenerator;
68
69 public static String divider, dividerRegex;
70
71 public static void main(String[] args) {
72 if (args.length < 6) {
73 System.out.println("Args count must be 6 or more");
74 System.exit(1);
75 }
76
77 String OS = System.getProperty("os.name").toLowerCase();
78 if(OS.contains("win")){
79 divider = "\\";
80 dividerRegex = "\\\\";
81 }else{
82 divider = "/";
83 dividerRegex = "/";
84 }
85
86 final int buildType = Integer.parseInt(args[0]);
87 String sourcePath = args[1];
88 String destinationPath = args[2];
89 packageName = args[3];
90 applicationId = args[4];
91 String sha1 = args[5];
92
93 javaGenerator = new GenerateJavaClass(packageName, buildType);
94
95
96 if (args.length > 6) {
97 targetFiles = new ArrayList<>();
98 for (int i = 6; i < args.length; i++) {
99 if (args[i].endsWith(".java")) {
100 String s = args[i].substring(0, args[i].indexOf(".java"));
101 targetFiles.add(s.replaceAll("\\.", dividerRegex) + ".java");
102 } else {
103 targetFiles.add(args[i].replaceAll("\\.", dividerRegex));
104 }
105 }
106 }
107
108 secretPreffix = getRandomBase64String(32);
109 sha = new String(Base64.getEncoder().encode(hexStringToByteArray(sha1.replaceAll(":", ""))));
110
111
112 final File origin = new File(sourcePath);
113 final File destination = new File(destinationPath);
114 if (!destination.exists()) {
115 destination.mkdirs();
116 }
117 System.out.println("original " + origin.toString() + " " + origin.isDirectory());
118 if (origin.isDirectory()) {
119 try {
120
121 Files.walkFileTree(origin.toPath(), new FileVisitor<Path>() {
122 private Path path = null;
123 private PathMatcher javaMatcher = FileSystems.getDefault().getPathMatcher("glob:**.java");
124 private PathMatcher kotlinMatcher = FileSystems.getDefault().getPathMatcher("glob:**.kt");
125
126 @Override
127 public FileVisitResult preVisitDirectory(Path path, BasicFileAttributes basicFileAttributes) throws IOException {
128 Files.createDirectories(destination.toPath().resolve(origin.toPath()
129 .relativize(path)));
130 if (path.toString().equals(origin.getPath() + divider + "app")) {
131 this.path = path;
132 }
133
134 if (path.toFile().getName().startsWith(".")) {
135 return FileVisitResult.SKIP_SUBTREE;
136 }
137 if (path.toString().equals(origin.getPath() + divider +"app" + divider +"build")) {
138 return FileVisitResult.SKIP_SUBTREE;
139 }
140 return FileVisitResult.CONTINUE;
141 }
142
143 @Override
144 public FileVisitResult visitFile(Path path, BasicFileAttributes basicFileAttributes) throws IOException {
145 if (this.path != null) {
146 if (javaMatcher.matches(path)) {
147 System.out.println("path " + path);
148 parsingJavaSourceCode(path, destination, origin);
149 }
150 else if(kotlinMatcher.matches(path)){
151 parsingKotlinSourceCode(path, destination, origin);
152 }
153 else {
154 Files.copy(path,
155 destination.toPath().resolve(origin.toPath().relativize(path)), StandardCopyOption.REPLACE_EXISTING);
156 }
157 } else {
158 Files.copy(path,
159 destination.toPath().resolve(origin.toPath().relativize(path)), StandardCopyOption.REPLACE_EXISTING);
160 }
161 return FileVisitResult.CONTINUE;
162 }
163
164 @Override
165 public FileVisitResult visitFileFailed(Path path, IOException e) throws IOException {
166 return FileVisitResult.CONTINUE;
167 }
168
169 @Override
170 public FileVisitResult postVisitDirectory(Path path, IOException e) throws IOException {
171 if (path.getFileName().toString().equals("app")) {
172 this.path = null;
173 }
174 return FileVisitResult.CONTINUE;
175 }
176 });
177 } catch (IOException e) {
178 e.printStackTrace();
179 }
180 }
181 generateDynamicCode(destination.getPath(), packageName, applicationId, sha);
182 System.out.println("Classes obfuscated: " + classCount);
183 System.out.println("Strings obfuscated: " + stringCount);
184
185 try {
186 final StringBuilder sb = new StringBuilder();
187 final boolean[] replacePlaceholder = {false, false, false, false};
188 Files.walk(destination.toPath()).filter(new Predicate<Path>() {
189 @Override
190 public boolean test(Path path) {
191 if (Files.isRegularFile(path)) {
192 return path.toString().endsWith(".java") ||
193 path.toString().endsWith(".txt") ||
194 path.toString().endsWith(".pro");
195 }
196 return false;
197 }
198 }).forEach(new Consumer<Path>() {
199 @Override
200 public void accept(Path path) {
201 try {
202 BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(path.toFile())));
203 String line = "";
204 boolean match = false;
205 while ((line = reader.readLine()) != null) {
206 if (line.contains(PLACEHOLDER)) {
207 match = true;
208 String[] s = line.split("<-#->");
209 if (s.length > 1) {
210 if(s[1].contains("A.b().e(this)")){
211 sb.append("\t\t").append(javaGenerator.mainClassName).append(".").append(javaGenerator.initializeMethodName).append("().").append(javaGenerator.mainDecodeMethod).append("(this);\n");
212 sb.insert(sb.indexOf("\n"), "\nimport " + packageName + "." + javaGenerator.getMainClassImport() + ";\n");
213 replacePlaceholder[2] = true;
214 }else if(s[1].contains("add_library") || s[1].contains("target_link_libraries")){
215 sb.append(s[1].replace("tttt", javaGenerator.libraryName).replace("bla.cpp", javaGenerator.cppFileName + ".cpp")).append("\n");
216 replacePlaceholder[1] = true;
217 } else if(s[1].contains("keep")) {
218 if(s[1].contains(".A")) {
219 sb.append(s[1].replace(".A", "." + (buildType == BUIL_TYPE_1 ? "" : (javaGenerator.getMainClassPackage() + ".")) + javaGenerator.mainClassName)).append("\n");
220 }else if(s[1].contains(".D")){
221 sb.append(s[1].replace(".D", "." + (buildType == BUIL_TYPE_1 ? "" : (javaGenerator.getSecondaryClassPackage() + ".")) + javaGenerator.secondaryClassName)).append("\n");
222
223 }
224 replacePlaceholder[0] = true;
225 }else{
226 sb.append(s[1]).append("\n");
227 }
228 }
229 } else {
230 sb.append(line).append("\n");
231 }
232 }
233 if (match) {
234 try {
235 Files.write(path, sb.toString().getBytes());
236 } catch (Exception e) {
237
238 }
239 }
240 sb.delete(0, sb.length());
241 } catch (Exception e) {
242 e.printStackTrace();
243 }
244 }
245 });
246
247
248 for (int i = 0; i < 3; i++) {
249 if (!replacePlaceholder[i]) {
250 System.out.println("Miss placeholder " + ((i == 0) ? "Proguard" : (i == 1) ? "Cmake" : "Init"));
251 System.exit(1);
252 }
253 }
254 } catch (Exception e) {
255 e.printStackTrace();
256 }
257 }
258
259 private static void parsingKotlinSourceCode(Path path, File destination, File origin) {
260 KotlinParser.parseSourceCode(path, destination, origin);
261 }
262
263 private static byte[] hexStringToByteArray(String s) {
264 int len = s.length();
265 byte[] data = new byte[len / 2];
266 for (int i = 0; i < len; i += 2) {
267 data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
268 + Character.digit(s.charAt(i + 1), 16));
269 }
270 return data;
271 }
272
273
274 public static String getRandomName(boolean isClass) {
275 int leftLimit = 97; // letter 'a'
276 int rightLimit = 122; // letter 'z'
277 Random random = new Random();
278 StringBuilder buffer = new StringBuilder();
279 int randomLimitedInt = leftLimit + (int) (random.nextFloat() * (rightLimit - leftLimit + 1));
280 if(isClass){
281 buffer.append(String.valueOf((char) randomLimitedInt).toUpperCase());
282 }else{
283 buffer.append((char) randomLimitedInt);
284 }
285 for(int i = 0; i < 3; i++){
286 int randomInt = random.nextInt(10);
287 buffer.append(randomInt);
288 }
289 randomLimitedInt = leftLimit + (int) (random.nextFloat() * (rightLimit - leftLimit + 1));
290 buffer.append((char) randomLimitedInt);
291 if(names.contains(buffer.toString())){
292 return getRandomName(isClass);
293 }
294 names.add(buffer.toString());
295 return buffer.toString();
296 }
297
298 static String getRandomBase64String(int bytes) {
299 Random random = ThreadLocalRandom.current();
300 byte[] r = new byte[bytes];
301 random.nextBytes(r);
302 return Base64.getEncoder().encodeToString(r);
303 }
304
305 private static void parsingJavaSourceCode(final Path path, File destination, File origin) {
306 final boolean[] match = {false};
307 InputStream in = null;
308 ParseResult<CompilationUnit> parseResult = null;
309 try {
310 in = Files.newInputStream(path);
311 parseResult = new JavaParser().parse(in);
312
313 boolean doProcess = true;
314 if (targetFiles != null && targetFiles.size() > 0) {
315 doProcess = false;
316 for (String s : targetFiles) {
317 if (path.toString().contains(s)) {
318 doProcess = true;
319 }
320 }
321 }
322 System.out.println("do proceswss " + doProcess);
323 if (doProcess) {
324 System.out.println("do proceswss");
325 if (parseResult.isSuccessful()) {
326 final Optional<CompilationUnit> optional = parseResult.getResult();
327 if (optional.isPresent()) {
328 optional.get().findAll(FieldDeclaration.class).forEach(new Consumer<FieldDeclaration>() {
329 @Override
330 public void accept(FieldDeclaration fieldDeclaration) {
331 fieldDeclaration.getVariables().forEach(new Consumer<VariableDeclarator>() {
332 @Override
333 public void accept(final VariableDeclarator variableDeclarator) {
334 if (variableDeclarator.getInitializer().isPresent() && variableDeclarator.getType().toString().equals("String")) {
335 if (!match[0]) {
336 optional.get().addImport(packageName + "." + javaGenerator.getMainClassImport());
337 match[0] = true;
338 classCount++;
339 }
340 if (variableDeclarator.getInitializer().get().isStringLiteralExpr()) {
341 obfuscateString(variableDeclarator.getInitializer().get().asStringLiteralExpr());
342 } else if (variableDeclarator.getInitializer().get().isBinaryExpr()) {
343 parseBinaryExpr(variableDeclarator.getInitializer().get());
344 } else {
345
346 }
347 }
348 }
349 });
350 }
351 });
352
353 optional.get().findAll(AssignExpr.class).forEach(new Consumer<AssignExpr>() {
354 @Override
355 public void accept(AssignExpr assignExpr) {
356 Expression expression = assignExpr.getValue();
357 if (expression.isStringLiteralExpr()) {
358 if (!match[0]) {
359 optional.get().addImport(packageName + "." + javaGenerator.getMainClassImport());
360 match[0] = true;
361 classCount++;
362 }
363 obfuscateString(expression.asStringLiteralExpr());
364 } else if (expression.isBinaryExpr()) {
365 if (!match[0]) {
366 optional.get().addImport(packageName + "." + javaGenerator.getMainClassImport());
367 match[0] = true;
368 classCount++;
369 }
370 parseBinaryExpr(expression.asBinaryExpr());
371 }
372 }
373 });
374
375 optional.get().findAll(ArrayInitializerExpr.class).forEach(new Consumer<ArrayInitializerExpr>() {
376 @Override
377 public void accept(ArrayInitializerExpr arrayInitializerExpr) {
378
379 NodeList<Expression> list = arrayInitializerExpr.getValues();
380 for (Expression exp : list) {
381 if (exp.isStringLiteralExpr()) {
382 if (!match[0]) {
383 optional.get().addImport(packageName + "." + javaGenerator.getMainClassImport());
384 match[0] = true;
385 classCount++;
386 }
387 obfuscateString(exp.asStringLiteralExpr());
388 } else if (exp.isBinaryExpr()) {
389 if (!match[0]) {
390 optional.get().addImport(packageName + "." + javaGenerator.getMainClassImport());
391 match[0] = true;
392 classCount++;
393 }
394 parseBinaryExpr(exp.asBinaryExpr());
395 }
396 }
397 }
398 });
399 }
400 }
401 }
402
403 Path p = destination.toPath().resolve(origin.toPath().relativize(path));
404 p.toFile().createNewFile();
405 Files.write(p, parseResult.getResult().get().toString().getBytes("UTF-8"));
406 } catch (Exception e) {
407 e.printStackTrace();
408 }
409 }
410
411 private static void parseBinaryExpr(Expression expression) {
412 if (expression.isBinaryExpr()) {
413 Expression left = expression.asBinaryExpr().getLeft();
414 parseBinaryExpr(left);
415 Expression right = expression.asBinaryExpr().getRight();
416 parseBinaryExpr(right);
417 } else {
418 if (expression.isStringLiteralExpr()) {
419 obfuscateString(expression.asStringLiteralExpr());
420 }
421 }
422 }
423
424 private static byte[] xorWithKey(byte[] source, byte[] key) {
425 byte[] result = new byte[source.length];
426 for (int i = 0; i < source.length; i++) {
427 result[i] = (byte) (source[i] ^ key[i % key.length]);
428 }
429 return result;
430 }
431
432 private static void obfuscateString(StringLiteralExpr expr) {
433 String value = expr.asStringLiteralExpr().getValue();
434 NodeList<Expression> list = new NodeList<>();
435 String uuid = UUID.nameUUIDFromBytes(value.getBytes()).toString();
436 generateEncryptedString(value, uuid, applicationId + secretPreffix);
437 String obfuscateString = new StringBuffer(Base64.getEncoder().encodeToString(xorWithKey(uuid.getBytes(), (applicationId + secretPreffix).getBytes()))).reverse().toString();
438 list.add(new StringLiteralExpr(obfuscateString));
439 if (expr.getParentNode().isPresent()) {
440 expr.getParentNode().get().replace(expr,
441 new MethodCallExpr().setName(javaGenerator.mainClassName + "." + javaGenerator.initializeMethodName + "()." + javaGenerator.decodeStringMethodName).setArguments(list));
442 }
443 stringCount++;
444 }
445
446 private static String generateEncryptedString(String value, String uuid, String key_package) {
447 String temp = Base64.getEncoder().encodeToString(xorWithKey(value.getBytes(), xorWithKey(uuid.getBytes(), key_package.getBytes())));
448 String value2 = uuid + "@@@" + temp + "***";
449 ciphrResultString.append(value2);
450 return temp;
451 }
452
453 private static void generateDynamicCode(String path, String packageName, String appId, String sha) {
454 String prefixJNICode = generatePreffixJNICode();
455 String packageJNIBytesRepresentation = generatePackageBytesRepresentation(appId.getBytes());
456 String shaMethod = generateSHA1JNICode(sha.getBytes());
457 String appIdMethod = generateAppIdJNICode(appId.getBytes());
458 String encodedMethod = generateEncodeJNICode(sha);
459 String uuid = UUID.nameUUIDFromBytes("#".getBytes()).toString();
460 JNIGenerate jni = new JNIGenerate(packageName, appIdMethod, prefixJNICode, packageJNIBytesRepresentation, shaMethod, encodedMethod, javaGenerator);
461 javaGenerator.tst = new StringBuffer(Base64.getEncoder().encodeToString(xorWithKey(uuid.getBytes(), (applicationId + secretPreffix).getBytes()))).reverse().toString();
462
463
464 ArrayList<Pair<String,String>> filesToWrite = javaGenerator.getFiles();
465 for(Pair<String,String> p : filesToWrite){
466 try{
467 File f = new File(path + "/app/src/main/java/" + packageName.replaceAll("\\.", "/") + "/" + p.a.replaceAll("\\.", "/") + ".java");
468 ensureFoldersExist(f.getParentFile());
469 f.createNewFile();
470 FileWriter fileWriter = new FileWriter(f);
471 fileWriter.write(p.b);
472 fileWriter.flush();
473 fileWriter.close();
474 }catch (Exception e){
475 e.printStackTrace();
476 System.exit(1);
477 }
478 }
479
480 try {
481 FileWriter fileWriter = new FileWriter(path + "/app/src/main/cpp/"+javaGenerator.cppFileName+".cpp");
482 fileWriter.write(jni.getJNIClass().toString());
483 fileWriter.flush();
484 fileWriter.close();
485 } catch (Exception e) {
486 e.printStackTrace();
487 System.exit(1);
488 }
489
490 if(jni.getJNI2Class() != null){
491 try {
492 FileWriter fileWriter = new FileWriter(path + "/app/src/main/cpp/"+javaGenerator.secondaryNativeClassName +".h");
493 fileWriter.write(jni.getJNI2Class().toString());
494 fileWriter.flush();
495 fileWriter.close();
496 } catch (Exception e) {
497 e.printStackTrace();
498 System.exit(1);
499 }
500 }
501 }
502
503 static void ensureFoldersExist(File folder) {
504 if (!folder.exists()) {
505 if (!folder.mkdirs()) {
506 ensureFoldersExist(folder.getParentFile());
507 }
508 }
509 }
510
511 private static String generateEncodeJNICode(String sha) {
512 try {
513 byte[] saltEncrypt = sha.getBytes();
514 SecretKeyFactory factoryKeyEncrypt = SecretKeyFactory
515 .getInstance("PBKDF2WithHmacSHA1");
516 SecretKey tmp = factoryKeyEncrypt.generateSecret(new PBEKeySpec(
517 secretPreffix.toCharArray(), saltEncrypt, 1024,
518 256));
519 SecretKeySpec encryptKey = new SecretKeySpec(tmp.getEncoded(), "AES");
520
521 Cipher aesCipherEncrypt = Cipher.getInstance("AES/CBC/PKCS5Padding");
522 aesCipherEncrypt.init(Cipher.ENCRYPT_MODE, encryptKey);
523
524 AlgorithmParameters params = aesCipherEncrypt.getParameters();
525 byte[] iv = params.getParameterSpec(IvParameterSpec.class).getIV();
526 byte[] bytes = aesCipherEncrypt.doFinal(ciphrResultString.toString().getBytes());
527
528 String result = Base64.getEncoder().withoutPadding().encodeToString(bytes);
529 StringBuilder sb = new StringBuilder();
530 sb.append("const char* encoded1 = \"").append(getRandomBase64String(1024)).append("\";\n");
531 sb.append("const char* encoded2 = \"").append(getRandomBase64String(256)).append("\";\n");
532 sb.append("const char* encoded3 = \"").append(getRandomBase64String(512)).append("\";\n");
533 sb.append("const char* encoded = \"").append(Base64.getEncoder().encodeToString(new StringBuffer(result).reverse().toString().getBytes())).append("\";\n");
534 sb.append("const char* iv = \"").append(Base64.getEncoder().encodeToString(iv)).append("\";\n");
535 sb.append("const char* iv1 = \"").append(getRandomBase64String(16)).append("\";\n");
536 sb.append("const char* iv2 = \"").append(getRandomBase64String(16)).append("\";\n");
537 sb.append("const char* ib0 = \"").append(getRandomBase64String(16)).append("\";\n");
538 return sb.toString();
539 } catch (Exception e) {
540 e.printStackTrace();
541 }
542 return "";
543 }
544
545 private static String generateAppIdJNICode(byte[] bytes) {
546 StringBuilder sb = new StringBuilder();
547 int length = bytes.length;
548 sb.append("void getApplicationId(char* appId) {\n").append("\tint count = 0;\n")
549 .append("\tcount = ").append(length).append(";\n")
550 .append("\tchar b[").append(length + 1).append("] = {'\\0'};\n")
551 .append("\tmemset(b, 0x0, ").append(length).append(");\n")
552 .append("\tmemset(appId, 0x0, ").append(length).append(");\n");
553
554 for (int j = 0; j < bytes.length; j++) {
555 int val = bytes[j];
556 String s = "";
557 StringBuilder temp = new StringBuilder();
558 boolean firstBit = false;
559 for (int i = 7; i >= 0; i--) {
560 if ((val & 128) == 0) {
561
562 } else {
563 if (i == 0) {
564 firstBit = true;
565 temp.insert(0, "\tb[" + j + "] = 1;\n");
566 } else {
567 temp.insert(0, "\tb[" + j + "] |= 1<<" + i + ";\n");
568 }
569 }
570 s = temp.toString();
571 if (!firstBit) {
572 s = s.replaceFirst(" \\|= ", " = ");
573 }
574 val <<= 1;
575 }
576 sb.append(s).append("\n");
577 }
578
579 sb.append("\n").append("\tfor (int i = 0; i < count; i++)\n")
580 .append("\t\tappId[i] = b[i];\n")
581 .append("}\n");
582
583 return sb.toString();
584 }
585
586 private static String generatePackageBytesRepresentation(byte[] bytes) {
587 int chunkSize = 9;
588 int rest = bytes.length % chunkSize;
589 int chunks = bytes.length / chunkSize + (rest > 0 ? 1 : 0);
590 int[][] arrays = new int[chunks][];
591 byte[] byteArray;
592 int count = 0;
593 for (int i = 0; i < (rest > 0 ? chunks - 1 : chunks); i++) {
594 byteArray = Arrays.copyOfRange(bytes, i * chunkSize, i * chunkSize + chunkSize);
595 arrays[i] = new int[byteArray.length];
596 for (int k = 0; k < byteArray.length; k++) {
597 if (i % 2 == 0) {
598 arrays[i][k] = (int) byteArray[k] + 1;
599 } else {
600 arrays[i][k] = (int) byteArray[k] - 1;
601 }
602 }
603 count += byteArray.length;
604 }
605 if (rest > 0) { // only when we have a rest
606 // we copy the remaining elements into the last chunk
607 byteArray = Arrays.copyOfRange(bytes, (chunks - 1) * chunkSize, (chunks - 1) * chunkSize + rest);
608 count += byteArray.length;
609 arrays[chunks - 1] = new int[byteArray.length];
610 for (int k = 0; k < byteArray.length; k++) {
611 if ((chunks - 1) % 2 == 0) {
612 arrays[chunks - 1][k] = (int) byteArray[k] + 1;
613 } else {
614 arrays[chunks - 1][k] = (int) byteArray[k] - 1;
615 }
616 }
617 }
618
619 StringBuilder sb = new StringBuilder();
620 for (int i = 0; i < arrays.length; i++) {
621 sb.append("int var").append(i + 10).append(" [").append(arrays[i].length).append("] = ")
622 .append(Arrays.toString(arrays[i]).replace("[", "{").replace("]", "};")).append("\n");
623 }
624
625 sb.append("const int count = ").append(count).append(";\n");
626 sb.append("int arraysCount = ").append(arrays.length).append(";\n");
627 sb.append("int arraysLength[").append(arrays.length).append("] = {");
628 for (int i = 0; i < arrays.length; i++) {
629 sb.append(arrays[i].length);
630 if (i < arrays.length - 1) {
631 sb.append(", ");
632 }
633 }
634 sb.append("};\n");
635 sb.append("int* var [").append(arrays.length).append("] = {");
636 for (int i = 0; i < arrays.length; i++) {
637 sb.append("var").append(i + 10);
638 if (i < arrays.length - 1) {
639 sb.append(", ");
640 }
641 }
642 sb.append("};\n");
643
644 return sb.toString();
645 }
646
647 private static String generatePreffixJNICode() {
648 byte[] bytes = secretPreffix.getBytes();
649 StringBuilder preffixJNI = new StringBuilder();
650 int length = bytes.length;
651 preffixJNI.append("void getSecretPrefix(char* prefix) {\n").append("\tint count = 0;\n")
652 .append("\tcount = ").append(length).append(";\n")
653 .append("\tchar b[").append(length + 1).append("] = {'\\0'};\n")
654 .append("\tmemset(b, 0x0, ").append(length).append(");\n")
655 .append("\tmemset(prefix, 0x0, ").append(length).append(");\n");
656
657 for (int j = 0; j < bytes.length; j++) {
658 int val = bytes[j];
659 String s = "";
660 StringBuilder temp = new StringBuilder();
661 boolean firstBit = false;
662 for (int i = 7; i >= 0; i--) {
663 if ((val & 128) == 0) {
664
665 } else {
666 if (i == 0) {
667 firstBit = true;
668 temp.insert(0, "\tb[" + j + "] = 1;\n");
669 } else {
670 temp.insert(0, "\tb[" + j + "] |= 1<<" + i + ";\n");
671 }
672 }
673 s = temp.toString();
674 if (!firstBit) {
675 s = s.replaceFirst(" \\|= ", " = ");
676 }
677 val <<= 1;
678 }
679 preffixJNI.append(s).append("\n");
680 }
681
682 preffixJNI.append("\n").append("\tfor (int i = 0; i < count; i++)\n")
683 .append("\tprefix[i] = b[i];\n")
684 .append("\t__android_log_print(ANDROID_LOG_ERROR, \"TAG %s\", \" print %s %s\", prefix, b);\n").append("}\n");
685
686
687 return preffixJNI.toString();
688 }
689
690 private static String generateSHA1JNICode(byte[] bytes) {
691 StringBuilder sb = new StringBuilder();
692 int length = bytes.length;
693 sb.append("void getSecretSHA(char* sha1) {\n").append("\tint count = 0;\n")
694 .append("\tcount = ").append(length).append(";\n")
695 .append("\tchar b[").append(length + 1).append("] = {'\\0'};\n")
696 .append("\tmemset(b, 0x0, ").append(length).append(");\n")
697 .append("\tmemset(sha1, 0x0, ").append(length).append(");\n");
698
699 for (int j = 0; j < bytes.length; j++) {
700 int val = bytes[j];
701 String s = "";
702 StringBuilder temp = new StringBuilder();
703 boolean firstBit = false;
704 for (int i = 7; i >= 0; i--) {
705 if ((val & 128) == 0) {
706
707 } else {
708 if (i == 0) {
709 firstBit = true;
710 temp.insert(0, "\tb[" + j + "] = 1;\n");
711 } else {
712 temp.insert(0, "\tb[" + j + "] |= 1<<" + i + ";\n");
713 }
714 }
715 s = temp.toString();
716 if (!firstBit) {
717 s = s.replaceFirst(" \\|= ", " = ");
718 }
719 val <<= 1;
720 }
721 sb.append(s).append("\n");
722 }
723
724 sb.append("\n").append("\tfor (int i = 0; i < count; i++)\n")
725 .append("\t\tsha1[i] = b[i];\n")
726 .append("}");
727
728 return sb.toString();
729 }
730}