난독화를 해제하려면 vlx-vmengine을 사용하세요.
vlx-vmengine-jvm 는 Java로 구현된 Java 바이트코드 실행 엔진입니다. 자세한 내용은 다음을 참조하십시오. https://github.com/vlinx-io/vlx-vmengine-jvm 사용 용도에 관하여.
간단한 조각이 있습니다. Java 코드는 다음과 같습니다.
class HelloWorld {
private String name = "";
public HelloWorld(String name){
this.name = name;
}
public void sayHi(){
System.out.println("Hi, " + name);
}
public static void main(String[] args){
String name = "George";
HelloWorld hello = new HelloWorld(name);
hello.sayHi();
}
}
클래스 파일로 컴파일하고 특정 난독화 엔진으로 난독화한 후 다음과 같은 파일들이 생성됩니다.
Jadx로 열어본 결과, 다음과 같은 사실이 밝혀졌습니다. main 함수 외에는 모든 정보를 알아볼 수 없으며 문자열은 암호화되었습니다.

하지만 혼란스럽더라도 클래스의 기본 구조와 바이트코드 정보는 여전히 존재합니다. 클래스뷰어 열기 a.class클래스의 메서드와 바이트코드 정보를 확인할 수 있습니다.

어떤 방식으로 코드를 난독화하든, 정적 수준에서만 코드를 혼란스럽게 하고 분석의 복잡성을 높일 뿐입니다. 동적 실행 시에는 프로그램의 원래 실행 로직을 복원해야 합니다. vlx-vmengine-jvm을 사용하여 난독화된 코드를 실행하면 이러한 문제를 해결할 수 있습니다. main 이 방법을 사용하면 다음과 같은 출력을 얻습니다.
2023-05-21 18:19:05 [DEBUG] LocalVars: [kotlin.Unit, kotlin.Unit, kotlin.Unit]
2023-05-21 18:19:05 [DEBUG] "L0: SIPUSH"
2023-05-21 18:19:05 [DEBUG] "push" 7144
2023-05-21 18:19:05 [DEBUG] "L3: SIPUSH"
2023-05-21 18:19:05 [DEBUG] "push" -13249
2023-05-21 18:19:05 [DEBUG] "L6: INVOKESTATIC"
2023-05-21 18:19:05 [DEBUG] "#20"
2023-05-21 18:19:05 [DEBUG] "class a, NameAndType(name='a', type='(II)Ljava/lang/String;')"
2023-05-21 18:19:05 [DEBUG] private static java.lang.String a.a(int,int)
2023-05-21 18:19:05 [DEBUG] "pop" -13249
2023-05-21 18:19:05 [DEBUG] "pop" 7144
2023-05-21 18:19:05 [DEBUG] Execute method: private static java.lang.String a.a(int,int)
2023-05-21 18:19:05 [DEBUG] Args: [7144, -13249]
2023-05-21 18:19:05 [DEBUG] "push" "George"
2023-05-21 18:19:05 [DEBUG] "L9: ASTORE_1"
2023-05-21 18:19:05 [DEBUG] "pop" "George"
2023-05-21 18:19:05 [DEBUG] "localVars[1] = George"
2023-05-21 18:19:05 [DEBUG] "L10: NEW"
2023-05-21 18:19:05 [DEBUG] class a
2023-05-21 18:19:05 [DEBUG] "push" InstanceToCreate(clazz=class a)
2023-05-21 18:19:05 [DEBUG] "L13: DUP"
2023-05-21 18:19:05 [DEBUG] "pop" InstanceToCreate(clazz=class a)
2023-05-21 18:19:05 [DEBUG] "push" InstanceToCreate(clazz=class a)
2023-05-21 18:19:05 [DEBUG] "push" InstanceToCreate(clazz=class a)
2023-05-21 18:19:05 [DEBUG] "L14: ALOAD_1"
2023-05-21 18:19:05 [DEBUG] "#1"
2023-05-21 18:19:05 [DEBUG] "push" "George"
2023-05-21 18:19:05 [DEBUG] "L15: INVOKESPECIAL"
2023-05-21 18:19:05 [DEBUG] "#47"
2023-05-21 18:19:05 [DEBUG] "class a, NameAndType(name='<init>', type='(Ljava/lang/String;)V')"
2023-05-21 18:19:05 [DEBUG] public a(java.lang.String)
2023-05-21 18:19:05 [DEBUG] "pop" "George"
2023-05-21 18:19:05 [DEBUG] "Execute new instance: public a(java.lang.String)"
2023-05-21 18:19:05 [DEBUG] "Args: [George]"
2023-05-21 18:19:05 [DEBUG] "pop" InstanceToCreate(clazz=class a)
2023-05-21 18:19:05 [DEBUG] "L18: ASTORE_2"
2023-05-21 18:19:05 [DEBUG] "pop" a@4612b856
2023-05-21 18:19:05 [DEBUG] "localVars[2] = a@4612b856"
2023-05-21 18:19:05 [DEBUG] "L19: ALOAD_2"
2023-05-21 18:19:05 [DEBUG] "#2"
2023-05-21 18:19:05 [DEBUG] "push" a@4612b856
2023-05-21 18:19:05 [DEBUG] "L20: INVOKEVIRTUAL"
2023-05-21 18:19:05 [DEBUG] "#54"
2023-05-21 18:19:05 [DEBUG] "class a, NameAndType(name='a', type='()V')"
2023-05-21 18:19:05 [DEBUG] public void a.a()
2023-05-21 18:19:05 [DEBUG] "pop" a@4612b856
2023-05-21 18:19:05 [DEBUG] Execute method: public void a.a()
2023-05-21 18:19:05 [DEBUG] Receiver: a@4612b856
2023-05-21 18:19:05 [DEBUG] Args: [a@4612b856]
Hi, George
2023-05-21 18:19:05 [DEBUG] "L23: RETURN"
콘솔 출력을 보면 프로그램이 원래 동작, 즉 출력하는 동작으로 복원되었음을 알 수 있습니다. Hi, George동시에 출력 결과를 통해 문자열 복호화 함수가 다음과 같다는 것도 확인할 수 있습니다. private static java.lang.String a.a(int,int)매개변수와 함께 7144 그리고 -13249만약 우리가 디버깅을 위해 vmengine을 계속 사용한다면 a.a(int,int) 이 방법을 통해 해당 난독화 엔진이 사용하는 문자열 암호화 방식을 알아낼 수 있습니다.