├── .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 |
--------------------------------------------------------------------------------