PageRenderTime 43ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/projects/sandmark-3.4/src/sandmark/obfuscate/encryptclasses/JarEncrypter.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 248 lines | 218 code | 29 blank | 1 comment | 25 complexity | fcfced21cea5255ba7ced7298b60ae05 MD5 | raw file
  1. package sandmark.obfuscate.encryptclasses;
  2. public class JarEncrypter extends sandmark.obfuscate.AppObfuscator {
  3. private static String KEY_ALG = "DESede";
  4. private static String CIPHER_ALG = "DESede/ECB/NoPadding";
  5. private static int KEY_SIZE = 112;
  6. private static String ENCRYPTED_LOADER_CURRENT_PATH =
  7. "/sandmark/obfuscate/encryptclasses/EncryptedClassLoader.class";
  8. private static String ENCRYPTED_LOADER_CLASS_NAME =
  9. "sandmark.obfuscate.encryptclasses.EncryptedClassLoader";
  10. private static String USAGE = "usage: java JarEncrypter plain.jar cipher.jar";
  11. private static String KEY_FIELD_NAME = "sKeyStr";
  12. private static String MAIN_CLASS_FIELD_NAME = "sMainClassName";
  13. private static char hexStr[] = new char[] {
  14. '0','1','2','3','4','5','6','7','8','9',
  15. 'a','b','c','d','e','f'
  16. };
  17. public void apply(sandmark.program.Application app) throws Exception {
  18. if(app.getClass(ENCRYPTED_LOADER_CLASS_NAME) != null)
  19. throw new IllegalArgumentException("Can't double encrypt");
  20. new sandmark.util.Publicizer().apply(app);
  21. java.security.Key key = generateKey(getConfigProperties().getProperty("Encryption Key"));
  22. javax.crypto.Cipher cipher =
  23. javax.crypto.Cipher.getInstance(CIPHER_ALG);
  24. System.out.println("cipher class: " + cipher.getClass());
  25. String mainClassName = app.getMain() == null ? null : app.getMain().getName();
  26. sandmark.program.Class classes[] = app.getClasses();
  27. for(int i = 0 ; i < classes.length ; i++) {
  28. sandmark.program.Class clazz = classes[i];
  29. cipher.init(javax.crypto.Cipher.ENCRYPT_MODE,key);
  30. byte fileBytes[] = clazz.getBytes();
  31. byte fileLengthBytes[] = new byte[] {
  32. (byte)((fileBytes.length >> 24) & 0xff),
  33. (byte)((fileBytes.length >> 16) & 0xff),
  34. (byte)((fileBytes.length >> 8) & 0xff),
  35. (byte)(fileBytes.length & 0xff),
  36. };
  37. byte encryptedLengthBytes[] = cipher.update(fileLengthBytes);
  38. byte encryptedFileBytes[] = cipher.update(fileBytes);
  39. byte encryptedLastBytes[] = cipher.doFinal(new byte[] { 0,0,0,0,0,0,0},0,(8 - ((4 + fileBytes.length) % 8)) % 8);
  40. byte allBytes[] = new byte[encryptedLengthBytes.length + encryptedFileBytes.length +
  41. encryptedLastBytes.length];
  42. System.arraycopy(encryptedLengthBytes,0,allBytes,0,encryptedLengthBytes.length);
  43. System.arraycopy(encryptedFileBytes,0,allBytes,encryptedLengthBytes.length,
  44. encryptedFileBytes.length);
  45. System.arraycopy(encryptedLastBytes,0,allBytes,
  46. encryptedLengthBytes.length + encryptedFileBytes.length,
  47. encryptedLastBytes.length);
  48. System.out.println("lengths: " + fileBytes.length + " " + encryptedLengthBytes.length + " " +
  49. encryptedFileBytes.length + " " + encryptedLastBytes.length +
  50. " " + allBytes.length);
  51. new sandmark.program.File(app,clazz.getJarName() + ".enc",allBytes);
  52. clazz.delete();
  53. }
  54. java.io.InputStream loaderStream =
  55. getClass().getResourceAsStream(ENCRYPTED_LOADER_CURRENT_PATH);
  56. org.apache.bcel.classfile.JavaClass jc = fixupLoader(loaderStream,mainClassName,key);
  57. sandmark.program.LocalClass lc = new sandmark.program.LocalClass(app,jc);
  58. app.setMain(lc);
  59. }
  60. public static void main(String argv[]) throws Throwable {
  61. if(argv.length != 2) {
  62. System.out.println(USAGE);
  63. System.exit(1);
  64. }
  65. sandmark.program.Application app =
  66. new sandmark.program.Application(argv[0]);
  67. JarEncrypter je = new JarEncrypter();
  68. je.apply(app);
  69. app.save(argv[1]);
  70. }
  71. private org.apache.bcel.classfile.JavaClass fixupLoader
  72. (java.io.InputStream is,String mainClassName,java.security.Key key)
  73. throws java.io.IOException {
  74. org.apache.bcel.classfile.JavaClass jc =
  75. new org.apache.bcel.classfile.ClassParser
  76. (is,ENCRYPTED_LOADER_CURRENT_PATH).parse();
  77. org.apache.bcel.generic.ClassGen cg =
  78. new org.apache.bcel.generic.ClassGen(jc);
  79. org.apache.bcel.generic.InstructionFactory factory =
  80. new org.apache.bcel.generic.InstructionFactory(cg);
  81. org.apache.bcel.classfile.Method meth = cg.containsMethod("<clinit>","()V");
  82. org.apache.bcel.generic.MethodGen newClInit = null, oldClInit = null;
  83. if(meth == null) {
  84. newClInit =
  85. new org.apache.bcel.generic.MethodGen
  86. (org.apache.bcel.Constants.ACC_PUBLIC,org.apache.bcel.generic.Type.VOID,
  87. new org.apache.bcel.generic.Type[0],new String[0],"<clinit>",
  88. cg.getClassName(),new org.apache.bcel.generic.InstructionList(),
  89. cg.getConstantPool());
  90. } else {
  91. org.apache.bcel.classfile.Method testMeth = null;
  92. int i = -1;
  93. do {
  94. i++;
  95. testMeth = cg.containsMethod("sm$ci" + i,"()V");
  96. } while(testMeth != null);
  97. newClInit =
  98. new org.apache.bcel.generic.MethodGen
  99. (meth,cg.getClassName(),cg.getConstantPool());
  100. oldClInit = (org.apache.bcel.generic.MethodGen)newClInit.clone();
  101. oldClInit.setName("sm$ci" + i);
  102. newClInit.setInstructionList
  103. (new org.apache.bcel.generic.InstructionList());
  104. newClInit.getInstructionList().append
  105. (factory.createInvoke
  106. (cg.getClassName(),oldClInit.getName(),org.apache.bcel.generic.Type.VOID,
  107. new org.apache.bcel.generic.Type[0],
  108. org.apache.bcel.Constants.INVOKESTATIC));
  109. }
  110. newClInit.removeLineNumbers();
  111. newClInit.removeLocalVariables();
  112. newClInit.getInstructionList().append
  113. ((new org.apache.bcel.generic.PUSH
  114. (cg.getConstantPool(),getKeyStr(key))).getInstruction());
  115. newClInit.getInstructionList().append
  116. (factory.createPutStatic(cg.getClassName(),KEY_FIELD_NAME,
  117. org.apache.bcel.generic.Type.STRING));
  118. if(mainClassName != null) {
  119. newClInit.getInstructionList().append
  120. ((new org.apache.bcel.generic.PUSH
  121. (cg.getConstantPool(),mainClassName)).getInstruction());
  122. newClInit.getInstructionList().append
  123. (factory.createPutStatic(cg.getClassName(),MAIN_CLASS_FIELD_NAME,
  124. org.apache.bcel.generic.Type.STRING));
  125. }
  126. newClInit.getInstructionList().append
  127. (new org.apache.bcel.generic.RETURN());
  128. newClInit.setMaxStack();
  129. if(meth == null) {
  130. cg.addMethod(newClInit.getMethod());
  131. } else {
  132. cg.replaceMethod(meth,newClInit.getMethod());
  133. cg.addMethod(oldClInit.getMethod());
  134. }
  135. //cg.setClassName(ENCRYPTED_LOADER_CLASS_NAME);
  136. return cg.getJavaClass();
  137. }
  138. private java.security.Key generateKey(String keyStr) throws
  139. java.security.NoSuchAlgorithmException,
  140. javax.crypto.NoSuchPaddingException,
  141. java.security.InvalidKeyException,
  142. javax.crypto.IllegalBlockSizeException,
  143. java.security.spec.InvalidKeySpecException {
  144. java.security.Key key;
  145. if(keyStr == null || keyStr.equals("") || !keyStr.startsWith("0x")) {
  146. javax.crypto.KeyGenerator keyGen =
  147. javax.crypto.KeyGenerator.getInstance(KEY_ALG);
  148. keyGen.init(KEY_SIZE);
  149. key = keyGen.generateKey();
  150. } else {
  151. byte keyBytes[] = new byte[(keyStr.length() - 2) / 2];
  152. for(int i = 0 ; i < keyBytes.length ; i++) {
  153. byte b1,b2;
  154. b1 = Byte.parseByte(keyStr.substring(2*(i + 1),2*(i + 1) + 1),16);
  155. b2 = Byte.parseByte(keyStr.substring(2*(i + 1) + 1,2*(i + 1) + 2),16);
  156. keyBytes[i] = (byte)((b1 << 4) | b2);
  157. }
  158. System.out.println("key length: " + keyBytes.length);
  159. for(int i = 0 ; i < keyBytes.length ; i++)
  160. System.out.print(keyBytes[i] + " ");
  161. System.out.println();
  162. javax.crypto.SecretKeyFactory skf =
  163. javax.crypto.SecretKeyFactory.getInstance(KEY_ALG);
  164. javax.crypto.spec.DESedeKeySpec keySpec =
  165. new javax.crypto.spec.DESedeKeySpec(keyBytes);
  166. key = skf.generateSecret(keySpec);
  167. }
  168. return key;
  169. }
  170. private String getKeyStr(java.security.Key key) {
  171. try {
  172. String secKey = "0x";
  173. byte bytes[] = key.getEncoded();
  174. for(int i = 0 ; i < bytes.length ; i++) {
  175. secKey += hexStr[(byte)((bytes[i] >> 4) & 0xf)];
  176. secKey += hexStr[(byte)(bytes[i] & 0xf)];
  177. }
  178. return secKey;
  179. } catch(Exception e) {
  180. return null;
  181. }
  182. }
  183. public String getShortName() { return "Class Encrypter"; }
  184. public String getLongName() {
  185. return "Encrypt Classes, Decrypt At Runtime";
  186. }
  187. public String getAlgHTML() {
  188. return
  189. "<HTML><BODY>" +
  190. "Class Encrypter encrypts class files and causes them to be decrypted " +
  191. "at runtime.\n" +
  192. "<TABLE>" +
  193. "<TR><TD>" +
  194. "Author: <A HREF = \"mailto:ash@huntwork.net\">Andrew Huntwork</A>" +
  195. "</TD></TR>" +
  196. "</TABLE>" +
  197. "</BODY></HTML>";
  198. }
  199. public String getAlgURL() { return "sandmark/obfuscate/encryptclasses/doc/help.html"; }
  200. private sandmark.util.ConfigProperties mProps;
  201. public sandmark.util.ConfigProperties getConfigProperties() {
  202. if(mProps == null) {
  203. String args[][] = {
  204. {"Encryption Key","","What key to use","","S"}
  205. };
  206. mProps =
  207. new sandmark.util.ConfigProperties
  208. (args,null);
  209. }
  210. return mProps;
  211. }
  212. public String getAuthor() { return "Andrew Huntwork"; }
  213. public String getAuthorEmail() { return "ash@huntwork.net"; }
  214. public String getDescription() {
  215. return "Class Encrypter encrypts class files and causes them to be decrypted " +
  216. "at runtime.";
  217. }
  218. public sandmark.config.ModificationProperty[] getMutations() { return null; }
  219. }