diff --git a/src/main/resources/jumbotron-image.1920e0770dc6.svg b/src/main/resources/jumbotron-image.1920e0770dc6.svg
new file mode 100644
index 00000000..6afa2d4a
--- /dev/null
+++ b/src/main/resources/jumbotron-image.1920e0770dc6.svg
@@ -0,0 +1,310 @@
+
+
+
+
diff --git a/src/main/resources/pyscripts/check_hash b/src/main/resources/pyscripts/check_hash
index b81af0a3..2aef3805 100644
--- a/src/main/resources/pyscripts/check_hash
+++ b/src/main/resources/pyscripts/check_hash
@@ -1,3 +1,9 @@
-main 96c29c93a496e6dbd73414157005a3f8
-removeComments 3c77e514c7a6095124abc318b6093150
-taintAnalysis 19202341a70ad86d09009a4653ca79a8
+stringSearch 0874410948a51042828b856410115e86
+main 50161042ab273d6dbf31845f33513254
+stringEncrypt f41b4195de585aac72cdd0fc7285f48c
+keyObfuscate 676fb4f92742441da501bbc27038a204
+stringObfuscate bf859f2f4f0c9117e99876726bfeed21
+stringInsert 0983fd34b3420bc1c654304cbc8c267c
+removeComments a7b260d4aa940c7cc818c321167cd1de
+taintAnalysis 7e55b0e079c4b4bfe3b88e980de0d7a6
+obfuscateTool bc032265f457512a38a4222dd1f7d085
diff --git a/src/main/resources/pyscripts/create_hash.py b/src/main/resources/pyscripts/create_hash.py
index ddf968a7..3332ee17 100644
--- a/src/main/resources/pyscripts/create_hash.py
+++ b/src/main/resources/pyscripts/create_hash.py
@@ -9,6 +9,7 @@ def calculate_md5(file_path):
md5_hash.update(byte_block)
return md5_hash.hexdigest()
+
def hash_files_in_directory(directory_path, exclude_file='create_hash.py', output_file='check_hash'):
"""디렉토리 내의 .py 파일들의 MD5 해시값을 계산하고 결과를 output_file에 저장합니다."""
with open(directory_path + output_file, 'w') as output:
diff --git a/src/main/resources/pyscripts/keyDecrypt.java b/src/main/resources/pyscripts/keyDecrypt.java
new file mode 100644
index 00000000..1227e5ea
--- /dev/null
+++ b/src/main/resources/pyscripts/keyDecrypt.java
@@ -0,0 +1,66 @@
+public static List keySchedule(byte[] key, int rounds) throws NoSuchAlgorithmException {
+ List schedule = new ArrayList<>();
+ schedule.add(key);
+
+ MessageDigest digest = MessageDigest.getInstance("SHA-256");
+ for (int i = 1; i < rounds; i++) {
+ byte[] newKey = digest.digest(schedule.get(schedule.size() - 1));
+ schedule.add(Arrays.copyOf(newKey, 16)); // 16바이트로 제한
+ }
+ return schedule;
+ }
+
+ public static byte[] inverseFeistelNetwork(byte[] block, byte[] roundKey) {
+ byte[] left = Arrays.copyOfRange(block, 0, 8);
+ byte[] right = Arrays.copyOfRange(block, 8, 16);
+ byte[] f_result = new byte[8];
+ for (int i = 0; i < 8; i++) {
+ f_result[i] = (byte) (left[i] ^ roundKey[i]);
+ }
+ byte[] newLeft = new byte[8];
+ for (int i = 0; i < 8; i++) {
+ newLeft[i] = (byte) (right[i] ^ f_result[i]);
+ }
+ return concatenate(newLeft, left);
+ }
+
+ public static byte[] keyDecryptAlg(byte[] data, byte[] key, int rounds) throws NoSuchAlgorithmException {
+ List keySched = keySchedule(key, rounds);
+ byte[] decrypted = new byte[data.length];
+ for (int i = 0; i < data.length; i += 16) {
+ byte[] block = Arrays.copyOfRange(data, i, i + 16);
+ for (int j = keySched.size() - 1; j >= 0; j--) {
+ block = inverseFeistelNetwork(block, keySched.get(j));
+ }
+ System.arraycopy(block, 0, decrypted, i, 16);
+ }
+ return removePadding(decrypted);
+ }
+
+ public static byte[] concatenate(byte[] a, byte[] b) {
+ byte[] result = new byte[a.length + b.length];
+ System.arraycopy(a, 0, result, 0, a.length);
+ System.arraycopy(b, 0, result, a.length, b.length);
+ return result;
+ }
+
+ public static byte[] removePadding(byte[] data) {
+ int i = data.length - 1;
+ while (i >= 0 && data[i] == 0) {
+ i--;
+ }
+ return Arrays.copyOf(data, i + 1);
+ }
+
+ public static byte[] keyDecrypt(String key, String key2) throws NoSuchAlgorithmException {
+ byte[] deckey = Base64.getDecoder().decode(key);
+ byte[] deckey2 = Base64.getDecoder().decode(key2);
+
+ byte[] decrypted_key = keyDecryptAlg(deckey, deckey2, 16);
+
+ return decrypted_key;
+ }
+
+
+
+
diff --git a/src/main/resources/pyscripts/keyObfuscate.py b/src/main/resources/pyscripts/keyObfuscate.py
new file mode 100644
index 00000000..eaed7408
--- /dev/null
+++ b/src/main/resources/pyscripts/keyObfuscate.py
@@ -0,0 +1,61 @@
+import hashlib
+
+class KeyObfuscate:
+ def __init__(self, aes_key, enc_key):
+ self.enc_aes_key = self.__key_encrypt(aes_key, enc_key)
+
+
+ def __key_schedule(self, key, rounds):
+ schedule = [key]
+ for i in range(1, rounds):
+ new_key = hashlib.sha256(schedule[-1]).digest()
+ schedule.append(new_key[:16]) # 16바이트로 제한
+ return schedule
+
+
+ def __feistel_network(self, block, round_key):
+ left, right = block[:8], block[8:]
+ f_result = bytes(a ^ b for a, b in zip(right, round_key[:8]))
+ new_right = bytes(a ^ b for a, b in zip(left, f_result))
+ return right + new_right
+
+
+ def __inverse_feistel_network(self, block, round_key):
+ left, right = block[:8], block[8:]
+ f_result = bytes(a ^ b for a, b in zip(left, round_key[:8]))
+ new_left = bytes(a ^ b for a, b in zip(right, f_result))
+ return new_left + left
+
+
+ def __encrypt(self, data, key, rounds=16):
+ key_sched = self.__key_schedule(key, rounds)
+ encrypted = bytearray()
+ for i in range(0, len(data), 16):
+ block = data[i:i+16]
+ if len(block) < 16:
+ block = block.ljust(16, b'\x00')
+ for round_key in key_sched:
+ block = self.__feistel_network(block, round_key)
+ encrypted.extend(block)
+ return bytes(encrypted)
+
+
+ def __decrypt(self, data, key, rounds=16):
+ key_sched = self.__key_schedule(key, rounds)
+ decrypted = bytearray()
+ for i in range(0, len(data), 16):
+ block = data[i:i+16]
+ for round_key in reversed(key_sched):
+ block = self.__inverse_feistel_network(block, round_key)
+ decrypted.extend(block)
+ return bytes(decrypted).rstrip(b'\x00')
+
+
+ def __key_encrypt(self, aes_key, key2):
+ enc2_aes_key = self.__encrypt(aes_key, key2)
+ return enc2_aes_key
+
+
+ def __key_decrypt(self, enc2_aes_key, key2):
+ enc_aes_key = self.__decrypt(enc2_aes_key, key2)
+ return enc_aes_key
\ No newline at end of file
diff --git a/src/main/resources/pyscripts/main.py b/src/main/resources/pyscripts/main.py
index 3c46f9a6..a88a106c 100644
--- a/src/main/resources/pyscripts/main.py
+++ b/src/main/resources/pyscripts/main.py
@@ -2,6 +2,8 @@
from taintAnalysis import taintAnalysis
from removeComments import removeComments
+from stringObfuscate import stringObfuscate
+
def create_taint_result(output_path, flows):
with open(output_path + "result.txt", 'w', encoding='utf-8') as file: # 결과 파일 생성
@@ -32,6 +34,7 @@ def main(java_folder_path, output_folder):
create_taint_result(output_folder, tainted.flows)
removeComments(output_folder)
+ stringObfuscate(output_folder)
if __name__ == '__main__':
diff --git a/src/main/resources/pyscripts/obfuscateTool.py b/src/main/resources/pyscripts/obfuscateTool.py
new file mode 100644
index 00000000..30e7e28e
--- /dev/null
+++ b/src/main/resources/pyscripts/obfuscateTool.py
@@ -0,0 +1,32 @@
+import random
+import javalang
+import os
+
+class obfuscateTool :
+ def random_class(class_list, random_count):
+ leng = len(class_list)
+ random_indices = [random.randint(0, leng - 1) for _ in range(random_count)]
+
+ random_class = [class_list[i] for i in random_indices]
+
+ return random_class
+
+
+ def parse_java_files(folder_path):
+ java_files = []
+
+ for root, _, files in os.walk(folder_path):
+ for file_name in files:
+ if file_name.endswith('.java'):
+ file_path = os.path.join(root, file_name)
+ with open(file_path, 'r', encoding='utf-8') as file:
+ source_code = file.read()
+ try:
+ tree = javalang.parse.parse(source_code)
+ java_files.append((file_path, tree, source_code))
+ except javalang.parser.JavaSyntaxError as e:
+ print(f"Syntax error in file {file_path}: {e}")
+ except Exception as e:
+ print(f"Error parsing file {file_path}: {e}")
+ return java_files
+
diff --git a/src/main/resources/pyscripts/removeComments.py b/src/main/resources/pyscripts/removeComments.py
index e037149a..87295bc1 100644
--- a/src/main/resources/pyscripts/removeComments.py
+++ b/src/main/resources/pyscripts/removeComments.py
@@ -1,37 +1,27 @@
from re import sub
-import os
+
+from obfuscateTool import obfuscateTool
+
class removeComments:
def __init__(self, project_path):
print("주석 제거 작업 시작...")
- self.__find_java_files(project_path)
+ self.__process_file(project_path)
print("주석 제거 완료.")
+ def __process_file(self, project_path):
+ java_files = obfuscateTool.parse_java_files(project_path)
- def __find_java_files(self, project_path):
- for root, _, files in os.walk(project_path):
- for file in files:
- if file.endswith('.java'):
- file_path = os.path.join(root, file)
- self.__process_file(file_path)
-
-
- def __process_file(self, file_path):
- with open(file_path, 'r', encoding='utf-8') as file:
- java_code = file.read()
-
- cleaned_code = self.__remove_comments(java_code)
+ for path, tree, source_code in java_files:
+ cleaned_code = self.__remove_comments(source_code)
+ with open(path, 'w', encoding='utf-8') as file:
+ file.write(cleaned_code)
+ print(f"Processed: {path}")
- with open(file_path, 'w', encoding='utf-8') as file:
- file.write(cleaned_code)
-
- print(f"Processed: {file_path}")
-
-
def __remove_comments(self, java_code):
# 문자열 내부의 주석 기호를 임시로 대체
code = sub(r'(".*?(? 1 else array_declaration
+ key_declaration_list = key_declaration_list.reverse() if len(key_declaration_list) > 1 else key_declaration_list
+
+ decrypt_code = f"""
+ static{{try {{Class> decryptorClass1 = Class.forName("{self.key_decrypt[0]}.{self.key_decrypt[1]}");
+ Method decryptMethod1 = decryptorClass1.getMethod("keyDecrypt", String.class, String.class);
+ Class> decryptorClass2 = Class.forName("{self.str_decrypt[0]}.{self.str_decrypt[1]}");
+ Method decryptMethod2 = decryptorClass2.getMethod("stringDecrypt", String.class, byte[].class);
+ for (int i = 0; i < STRING_LITERALS.length; i++)
+ {{STRING_LITERALS[i] =
+ (String) decryptMethod2.invoke(null, STRING_LITERALS[i],
+ (byte[]) decryptMethod1.invoke(null,ENC_ENCRYPTION_KEY,
+ ENCRYPTION_KEY));
+ }}}} catch (Exception e) {{}}}}
+ """
+
+ for i,pos in enumerate(classes_pos):
+ lines.insert(pos,array_declaration[i])
+ lines.insert(pos+1,key_declaration_list[i])
+ lines.insert(pos+2,decrypt_code)
+
+ reflection = 'import java.lang.reflect.Method;'
+ if reflection not in lines:
+ lines.insert(1, reflection)
+
+ code = '\n'.join(lines)
+
+ return code
\ No newline at end of file
diff --git a/src/main/resources/pyscripts/stringObfuscate.py b/src/main/resources/pyscripts/stringObfuscate.py
new file mode 100644
index 00000000..7bf31ef3
--- /dev/null
+++ b/src/main/resources/pyscripts/stringObfuscate.py
@@ -0,0 +1,14 @@
+from stringSearch import stringSearch
+from stringEncrypt import stringEncrypt
+from stringInsert import stringInsert
+
+from obfuscateTool import obfuscateTool
+
+class stringObfuscate :
+ def __init__(self, output_folder) :
+ search_str = stringSearch(output_folder)
+ random_classes = obfuscateTool.random_class(search_str.class_names, 2)
+
+ encrypt_str = stringEncrypt(search_str.Literals)
+
+ insert_str = stringInsert(search_str.Literals,encrypt_str.encrypted_Literals,random_classes,output_folder)
\ No newline at end of file
diff --git a/src/main/resources/pyscripts/stringSearch.py b/src/main/resources/pyscripts/stringSearch.py
new file mode 100644
index 00000000..774298f6
--- /dev/null
+++ b/src/main/resources/pyscripts/stringSearch.py
@@ -0,0 +1,32 @@
+import javalang
+
+from obfuscateTool import obfuscateTool
+
+class stringSearch:
+ def __init__(self, java_folder_path):
+ self.class_names = []
+ self.trees = obfuscateTool.parse_java_files(java_folder_path)
+ self.Literals = self.__extract_string_literals(self.trees) # [package,class,[Literals,,]] 이렇게 넣을 예정
+
+
+ # trees 에서 각 tree 의 문자열들을 추출하고 Literals 에 package_class 와 함께 저장
+ def __extract_string_literals(self, trees):
+ Literals = []
+ string_literals = []
+ package_name = None
+ class_name = None
+ for file_path, tree, source_code in trees:
+ for path, node in tree:
+ if isinstance(node, javalang.tree.PackageDeclaration):
+ package_name = node.name
+
+ if isinstance(node, javalang.tree.ClassDeclaration): # 근데 클래스 밖에있는 문자열, 다른클래스에서 특정 클래스의 문자열을 불러온다면?
+ string_literals = []
+ class_name = node.name
+ self.class_names.append([package_name,class_name])
+ for sub_path,sub_node in node:
+ if isinstance(sub_node, javalang.tree.Literal) and isinstance(sub_node.value, str) and sub_node.value.startswith('"') and sub_node.value.endswith('"'):
+ #literal = sub_node.value[1:-1]
+ string_literals.append((sub_node.value, sub_node.position))
+ Literals.append([package_name,class_name,string_literals]) # 클래스 별로 문자열 추출
+ return Literals
\ No newline at end of file
diff --git a/src/main/resources/pyscripts/taintAnalysis.py b/src/main/resources/pyscripts/taintAnalysis.py
index b0812539..dc8f877e 100644
--- a/src/main/resources/pyscripts/taintAnalysis.py
+++ b/src/main/resources/pyscripts/taintAnalysis.py
@@ -9,6 +9,7 @@ class taintAnalysis:
__flow = []
flows = defaultdict(list)
+
#메서드 단위로 AST 노드 저장, Taint 변수 탐색 및 저장
def __init__(self, java_folder_path):
# Step 1: Parse all Java files