├── .gitattributes └── src ├── com └── seaboat │ └── bytecode │ ├── ByteCodeEncryptor.java │ └── JarEncryptor.java ├── native ├── com_seaboat_bytecode_ByteCodeEncryptor.cpp └── com_seaboat_bytecode_ByteCodeEncryptor.h └── test ├── ByteCodeEncryptorTest.java └── JarEncryptorTest.java /.gitattributes: -------------------------------------------------------------------------------- 1 | *.java linguist-language=c -------------------------------------------------------------------------------- /src/com/seaboat/bytecode/ByteCodeEncryptor.java: -------------------------------------------------------------------------------- 1 | package com.seaboat.bytecode; 2 | /** 3 | * 4 | * @author seaboat 5 | * @date 2017-07-06 6 | * @version 1.0 7 | *
email: 849586227@qq.com
8 | *
blog: http://blog.csdn.net/wangyangzhizhou
9 | *

ByteCodeEncryptor provides a native encrypt method.

10 | */ 11 | public class ByteCodeEncryptor { 12 | static{ 13 | System.loadLibrary("ByteCodeEncryptor"); 14 | } 15 | 16 | public native static byte[] encrypt(byte[] text); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/com/seaboat/bytecode/JarEncryptor.java: -------------------------------------------------------------------------------- 1 | package com.seaboat.bytecode; 2 | 3 | import java.io.ByteArrayOutputStream; 4 | import java.io.File; 5 | import java.io.FileOutputStream; 6 | import java.io.InputStream; 7 | import java.util.Enumeration; 8 | import java.util.jar.JarEntry; 9 | import java.util.jar.JarFile; 10 | import java.util.jar.JarOutputStream; 11 | 12 | /** 13 | * 14 | * @author seaboat 15 | * @date 2017-07-06 16 | * @version 1.0 17 | *
email: 849586227@qq.com
18 | *
blog: http://blog.csdn.net/wangyangzhizhou
19 | *

encrypts jar.

20 | */ 21 | public class JarEncryptor { 22 | 23 | public static void encrypt(String fileName){ 24 | try { 25 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); 26 | byte[] buf = new byte[1024]; 27 | File srcFile = new File(fileName); 28 | File dstFile = new File(fileName.substring(0, fileName.indexOf("."))+"_encrypted.jar"); 29 | FileOutputStream dstFos = new FileOutputStream(dstFile); 30 | JarOutputStream dstJar = new JarOutputStream(dstFos); 31 | JarFile srcJar = new JarFile(srcFile); 32 | for (Enumeration enumeration = srcJar.entries(); enumeration.hasMoreElements();) { 33 | JarEntry entry = enumeration.nextElement(); 34 | InputStream is = srcJar.getInputStream(entry); 35 | int len; 36 | while ((len = is.read(buf, 0, buf.length)) != -1) { 37 | baos.write(buf, 0, len); 38 | } 39 | byte[] bytes = baos.toByteArray(); 40 | String name = entry.getName(); 41 | if(name.endsWith(".class")){ 42 | try { 43 | bytes = ByteCodeEncryptor.encrypt(bytes); 44 | } catch (Exception e) { 45 | e.printStackTrace(); 46 | } 47 | } 48 | JarEntry ne = new JarEntry(name); 49 | dstJar.putNextEntry(ne); 50 | dstJar.write(bytes); 51 | baos.reset(); 52 | } 53 | srcJar.close(); 54 | dstJar.close(); 55 | dstFos.close(); 56 | } catch (Exception e) { 57 | e.printStackTrace(); 58 | } 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/native/com_seaboat_bytecode_ByteCodeEncryptor.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "com_seaboat_bytecode_ByteCodeEncryptor.h" 4 | #include "jni.h" 5 | #include 6 | #include 7 | 8 | 9 | void encode(char *str) 10 | { 11 | unsigned int m = strlen(str); 12 | for (int i = 0; i < m; i++) 13 | { 14 | //str[i] = ((str[i] - 97)*k) - ((str[i] - 97)*k) / q*q + 97; 15 | str[i] = str[i] + k; 16 | } 17 | 18 | } 19 | 20 | void decode(char *str) 21 | { 22 | unsigned int m = strlen(str); 23 | //int k2 = (q + 1) / k; 24 | for (int i = 0; i < m; i++) 25 | { 26 | //str[i] = ((str[i] - 97)*k2) - ((str[i] - 97)*k2) / q*q + 97; 27 | str[i] = str[i] - k; 28 | } 29 | } 30 | 31 | 32 | extern"C" JNIEXPORT jbyteArray JNICALL 33 | Java_com_seaboat_bytecode_ByteCodeEncryptor_encrypt(JNIEnv * env, jclass cla, jbyteArray text) 34 | { 35 | char* dst = (char*)env->GetByteArrayElements(text, 0); 36 | encode(dst); 37 | env->SetByteArrayRegion(text, 0, strlen(dst), (jbyte *)dst); 38 | return text; 39 | } 40 | 41 | 42 | void JNICALL ClassDecryptHook( 43 | jvmtiEnv *jvmti_env, 44 | JNIEnv* jni_env, 45 | jclass class_being_redefined, 46 | jobject loader, 47 | const char* name, 48 | jobject protection_domain, 49 | jint class_data_len, 50 | const unsigned char* class_data, 51 | jint* new_class_data_len, 52 | unsigned char** new_class_data 53 | ) 54 | { 55 | *new_class_data_len = class_data_len; 56 | jvmti_env->Allocate(class_data_len, new_class_data); 57 | 58 | unsigned char* _data = *new_class_data; 59 | 60 | if (name&&strncmp(name, "com/seaboat/", 12) == 0) { 61 | for (int i = 0; i < class_data_len; i++) 62 | { 63 | _data[i] = class_data[i]; 64 | } 65 | decode((char*)_data); 66 | } 67 | else { 68 | for (int i = 0; i < class_data_len; i++) 69 | { 70 | _data[i] = class_data[i]; 71 | } 72 | } 73 | 74 | } 75 | 76 | JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *vm, char *options, void *reserved) 77 | { 78 | 79 | jvmtiEnv *jvmti; 80 | //Create the JVM TI environment(jvmti) 81 | jint ret = vm->GetEnv((void **)&jvmti, JVMTI_VERSION); 82 | if (JNI_OK != ret) 83 | { 84 | printf("ERROR: Unable to access JVMTI!\n"); 85 | return ret; 86 | } 87 | jvmtiCapabilities capabilities; 88 | (void)memset(&capabilities, 0, sizeof(capabilities)); 89 | 90 | capabilities.can_generate_all_class_hook_events = 1; 91 | capabilities.can_tag_objects = 1; 92 | capabilities.can_generate_object_free_events = 1; 93 | capabilities.can_get_source_file_name = 1; 94 | capabilities.can_get_line_numbers = 1; 95 | capabilities.can_generate_vm_object_alloc_events = 1; 96 | 97 | jvmtiError error = jvmti->AddCapabilities(&capabilities); 98 | if (JVMTI_ERROR_NONE != error) 99 | { 100 | printf("ERROR: Unable to AddCapabilities JVMTI!\n"); 101 | return error; 102 | } 103 | 104 | jvmtiEventCallbacks callbacks; 105 | (void)memset(&callbacks, 0, sizeof(callbacks)); 106 | 107 | callbacks.ClassFileLoadHook = &ClassDecryptHook; 108 | error = jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks)); 109 | if (JVMTI_ERROR_NONE != error) { 110 | printf("ERROR: Unable to SetEventCallbacks JVMTI!\n"); 111 | return error; 112 | } 113 | 114 | error = jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_CLASS_FILE_LOAD_HOOK, NULL); 115 | if (JVMTI_ERROR_NONE != error) { 116 | printf("ERROR: Unable to SetEventNotificationMode JVMTI!\n"); 117 | return error; 118 | } 119 | 120 | return JNI_OK; 121 | } 122 | 123 | -------------------------------------------------------------------------------- /src/native/com_seaboat_bytecode_ByteCodeEncryptor.h: -------------------------------------------------------------------------------- 1 | /* DO NOT EDIT THIS FILE - it is machine generated */ 2 | #include 3 | /* Header for class com_seaboat_bytecode_ByteCodeEncryptor */ 4 | 5 | #ifndef _Included_com_seaboat_bytecode_ByteCodeEncryptor 6 | #define _Included_com_seaboat_bytecode_ByteCodeEncryptor 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | /* 11 | * Class: com_seaboat_bytecode_ByteCodeEncryptor 12 | * Method: encrypt 13 | * Signature: ([B)[B 14 | */ 15 | JNIEXPORT jbyteArray JNICALL Java_com_seaboat_bytecode_ByteCodeEncryptor_encrypt 16 | (JNIEnv *, jclass, jbyteArray); 17 | 18 | #ifdef __cplusplus 19 | } 20 | #endif 21 | #endif 22 | #ifndef CONST_HEADER_H_ 23 | #define CONST_HEADER_H_ 24 | const int k = 4; 25 | const int q = 26; 26 | #endif // CONST_HEADER_H_ 27 | -------------------------------------------------------------------------------- /src/test/ByteCodeEncryptorTest.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | import com.seaboat.bytecode.ByteCodeEncryptor; 4 | /** 5 | * 6 | * @author seaboat 7 | * @date 2017-07-06 8 | * @version 1.0 9 | *
email: 849586227@qq.com
10 | *
blog: http://blog.csdn.net/wangyangzhizhou
11 | *

ByteCodeEncryptor tester.

12 | */ 13 | public class ByteCodeEncryptorTest { 14 | 15 | public static void main(String[] args) { 16 | byte[] texts = "qwertyuio".getBytes(); 17 | for (byte b : texts) 18 | System.out.println(b); 19 | System.out.println("==========="); 20 | byte[] bytes = ByteCodeEncryptor.encrypt(texts); 21 | for (byte b : bytes) 22 | System.out.println(b); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/test/JarEncryptorTest.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | 4 | import com.seaboat.bytecode.JarEncryptor; 5 | /** 6 | * 7 | * @author seaboat 8 | * @date 2017-07-06 9 | * @version 1.0 10 | *
email: 849586227@qq.com
11 | *
blog: http://blog.csdn.net/wangyangzhizhou
12 | *

JarEncryptor tester.

13 | */ 14 | public class JarEncryptorTest { 15 | 16 | public static void main(String[] args){ 17 | JarEncryptor.encrypt("C:\\Users\\wj\\Desktop\\test.jar"); 18 | } 19 | } 20 | --------------------------------------------------------------------------------