
다기능 자바 디난독화 도구 모음
Threadtear는 Java용 다기능 난독 해제 도구입니다. Android 애플리케이션 지원은 곧 제공될 예정입니다(현재 dalvik to Java 변환기를 작업 중입니다). 난독화에 대해 너무 걱정하지 않고 코드 분석을 더 쉽게 할 수 있습니다. ZKM이나 Stringer 같은 가장 비싼 난독화 도구도 포함되어 있습니다. 디버깅을 더 쉽게 하기 위한 다른 도구들도 포함되어 있습니다. 예외가 발생한 원인을 더 잘 이해할 수 있도록 디버그 라인 번호를 삽입하거나, 코드를 다시 컴파일하지 않고 try-catch 블록에 .printStackTrace()를 추가할 수 있습니다. 버전별 메서드를 사용하지 않는 이상, 역호환성은 더 이상 문제가 되지 않습니다. 그래프로 코드 흐름을 분석하여 알고리즘을 더 잘 이해할 수 있습니다.

"실행"은 실행되어 로드된 모든 클래스 파일을 수정하는 작업입니다. 바이트코드 정리부터 문자열 난독 해제까지 다양한 유형의 실행이 있습니다. 올바른 순서로 배치해야 합니다. 예를 들어 정리 실행은 마지막에 실행되어야 하지만, 먼저 실행하면 다른 실행에도 도움이 될 수 있습니다. 준비가 되면 "Run" 버튼을 클릭하면 순서대로 실행됩니다.
이 도구는 사용자의 책임 하에 사용하십시오. 일부 실행은 jar 파일에서 코드를 실행하기 위해 구현된 ClassLoader를 사용합니다. 공격자가 바이트코드를 조작하여 악성 코드가 실행될 수 있습니다. 영향을 받는 실행은 me.nov.threadtear.asm.vm.VM 클래스를 사용합니다. 이는 주로 문자열 또는 리소스/접근 난독화를 해독하는 데 사용되며, 원격으로 해독 메서드를 실행하는 것이 훨씬 쉽기 때문입니다.
Threadtear는 자체 SecurityManager를 사용하여 악성 호출(임의 코드 실행)로부터 사용자를 보호하기 위해 최선을 다하지만, 보장할 수는 없습니다. 특히 ZKM이나 Stringer와 같은 난독 해제 도구의 경우 리플렉션을 허용해야 하므로 매우 주의해야 합니다. 그렇지 않으면 제대로 작동하지 않습니다. ACE(임의 코드 실행)를 발견하면 이슈를 열어 주십시오. 가능한 한 빨리 수정하겠습니다.
먼저 gradle build를 실행한 다음 gradle fatJar를 실행합니다. builds/libs에 실행 가능한 jar 파일이 생성됩니다. 저장소를 다운로드하고 싶지 않다면 최신 릴리스를 사용할 수 있습니다.
자신만의 실행 작업을 쉽게 만들 수 있습니다. me.nov.threadtear.execution.Execution을 확장하기만 하면 됩니다:
public class MyExecution extends Execution {
public MyExecution() {
super(ExecutionCategory.CLEANING /* category */, "My execution" /* name */,
"Executes something" /* description, can use html */);
}
/**
* 이 메서드는 사용자가 Run 버튼을 클릭할 때 호출됩니다.
* @return 성공 시 true, 실패 시 false
*/
@Override
public boolean execute(Map<String, Clazz> classes, boolean verbose) {
classes.values().stream().map(c -> c.node).forEach(c -> {
//ASM의 tree-API를 사용하여 여기서 클래스를 변환합니다.
});
return false;
}
}
런타임에 ClassNode를 로드하려면 me.nov.threadtear.asm.vm.VM 클래스와 me.nov.threadtear.asm.vm.IVMReferenceHandler를 구현하십시오:
public class MyExecution extends Execution implements IVMReferenceHandler {
public MyExecution() {
super(ExecutionCategory.GENERIC, "My execution", "Loads ClassNodes at runtime");
}
@Override
public boolean execute(Map<String, Clazz> classes, boolean verbose) {
classes.values().stream().map(c -> c.node).forEach(c -> {
VM vm = VM.constructVM(this);
//바이트코드를 java.lang.Class로 변환
Class<?> loadedClass = vm.loadClass(c.name.replace('/', '.'), true);
//여기서 클래스로 작업 수행
loadedClass.getMethods()[0].invoke(...);
return true;
});
}
/**
* VM.loadClass가 호출될 때 VM에 의해 호출됩니다.
*/
@Override
public ClassNode tryClassLoad(String name) {
//열린 jar 아카이브에서 로드할 클래스를 찾으려고 시도합니다.
return classes.containsKey(name) ? classes.get(name).node : null;
}
}
ConstantTracker (me.nov.threadtear.analysis.stack.ConstantTracker)를 사용하면 메서드를 분석하고 변수가 아닌 스택 값을 추적할 수 있습니다. 예를 들어 iconst_0이 스택에 푸시되면 기본 ASM 분석기처럼 값이 손실되지 않고 이후 코드에서 예측하는 데 사용할 수 있습니다.
public class MyExecution extends Execution implements IConstantReferenceHandler {
public MyExecution() {
super(ExecutionCategory.GENERIC, "My execution", "Performs stack analysis and replaces code.");
}
@Override
public boolean execute(Map<String, Clazz> classes, boolean verbose) {
classes.values().stream().map(c -> c.node).forEach(this::analyzeAndRewrite);
return true;
}
public void analyzeAndRewrite(ClassNode cn) {
cn.methods.forEach(m -> {
// 이 분석기는 알려진 스택 값을 유지합니다. 예를 들어 점프 예측에 유용할 수 있습니다.
Analyzer<ConstantValue> a = new Analyzer<ConstantValue>(new ConstantTracker(this, Access.isStatic(m.access), m.maxLocals, m.desc, new Object[0]));
try {
a.analyze(cn.name, m);
} catch (AnalyzerException e) {
logger.severe("Failed stack analysis in " + cn.name + "." + m.name + ":" + e.getMessage());
return;
}
Frame<ConstantValue>[] frames = a.getFrames();
InsnList rewrittenCode = new InsnList();
Map<LabelNode, LabelNode> labels = Instructions.cloneLabels(m.instructions);
// 메서드 명령어 다시 작성
for (int i = 0; i < m.instructions.size(); i++) {
AbstractInsnNode ain = m.instructions.get(i);
Frame<ConstantValue> frame = frames[i];
// 명령어 대체/수정 등...
if (frame.getStackSize() > 0) {
ConstantValue top = frame.getStack(frame.getStackSize() - 1);
if (top.isKnown() && top.isInteger()) {
int knownTopStackValue = top.getInteger();
// 알려진 스택을 사용하여 점프 제거, 코드 단순화 등...
// if(...) { rewrittenCode.add(...); }
continue;
}
}
rewrittenCode.add(ain.clone(labels));
}
// 명령어 업데이트 및 try-catch 블록, 지역 변수 등 수정
Instructions.updateInstructions(m, labels, rewrittenCode);
});
}
/**
* 필드가 로드될 때 스택 값을 예측하려면 이 메서드를 사용하십시오.
*/
@Override
public Object getFieldValueOrNull(BasicValue v, String owner, String name, String desc) {
return null;
}
/**
* 알려진 객체에서 메서드가 호출될 때 스택 값을 예측하려면 이 메서드를 사용하십시오.
*/
@Override
public Object getMethodReturnOrNull(BasicValue v, String owner, String name, String desc, List<? extends ConstantValue> values) {
if (name.equals("toCharArray") && owner.equals("java/lang/String")) {
if (!values.get(0).isKnown()) {
// 호출 대상이 알려지지 않았으므로 반환 값을 계산할 수 없음
return null;
}
return ((String) values.get(0).getValue()).toCharArray();
}
return null;
}
}
me.nov.threadtear.execution.ExecutionLink의 트리에 자신의 실행을 추가하는 것을 잊지 마십시오!
jar 파일을 성공적으로 식별하고 난독 해제하는 데 도움이 되는 몇 가지 요령이 있습니다. 실행을 실행하기 전에 코드를 역컴파일하여 무엇을 사용해야 하는지 알아내십시오. 이를 위해 내장된 역컴파일러를 사용할 수 있습니다.
가장 좋은 난독 해제 순서는 일반 실행 > 접근 난독 해제 > 문자열 난독 해제 > 정리 실행입니다.
난독화 도구는 식별에 사용할 수 있는 패턴을 보여줍니다. 난독화 도구를 식별하는 가장 쉬운 방법은 META-INF/MANIFEST.MF 파일을 훑어보는 것입니다. Obfuscated-By: XXX 또는 Protected-By: XXX 속성이 있을 수 있습니다.
매우 (흐름) 난독화된 코드로, 종종 정적 초기화자의 스위치를 포함한 문자열 해독 메서드나 매우 긴 스위치 블록(약 250개 case)을 가진 문자열 해독 메서드로 인식할 수 있습니다. ZKM은 Java용 최고(이자 가장 오래된) 난독화 도구 중 하나이며 매우 비쌉니다. 웹사이트만큼이나 오래된 난독화 도구입니다.

jar 파일에 문자열 난독화 및 접근 난독화에 사용되는 거대한 해독 알고리즘을 가진 특별한 클래스가 포함되어 있다면 아마 Stringer일 것입니다. 보호 수준은 나쁘지 않으며 Stringer는 가장 비싼 난독화 도구 중 하나입니다. 일반적인 난독화 도구와 달리 이름 난독화를 제공하지 않습니다. 오히려 "두 번째 계층"으로 사용됩니다. 이 난독화 도구를 사용하는 사람들의 약 90%는 크랙을 사용하고 있을 것입니다. 자동차보다 비싸기 때문입니다. 파일이 여러 난독화 도구로 난독화되었고 그중 하나가 Stringer라면, Stringer 난독화는 덮어쓸 수 없으므로 Stringer부터 난독 해제를 시작해야 합니다. (사용자 지정 JAR 서명 및 문자열 해독 중 메서드 이름 사용으로 인해)

IiIlIlIiIl 또는 aUx, cOn, PrX와 같은 클래스 이름은 Allatori 난독화를 나타냅니다. Allatori는 몇 번의 클릭으로 액세스할 수 있는 무료 데모를 제공하기 때문에 난독화된 jar 파일에서 매우 흔합니다. 난독화를 역전시키는 것은 그리 어렵지 않습니다.

Paramorphism은 Stringer의 작은 형제와 같습니다. 비슷해 보이지만 그만큼 좋지는 않습니다. 역공학 도구를 충돌시키려는 흥미로운 기능도 있지만 쉽게 제거할 수 있습니다. 난독화 강도는 Allatori와 비슷합니다.

다른 난독화 도구의 경우 일반 실행을 시도하거나 이슈를 열면 제가 무엇을 할 수 있는지 살펴보겠습니다.
실행을 선택하기 전에 마우스를 올렸을 때 나타나는 도구 설명 텍스트를 확인하십시오. 수행하는 작업에 대한 간단한 설명이 포함되어 있으며, JAR 파일의 동작이 어떻게 변경될지 이해하는 데 도움이 되는 태그도 있습니다.
Threadtear는 GNU General Public License 3.0에 따라 라이선스가 부여됩니다.
이 도구는 엄청난 작업이었습니다. 제가 여러분의 시간을 절약해 주었다면, 여기에서 커피 한 잔 사주실 수 있습니다: Bitcoin으로 기부
Threadtear는 법적 목적으로만 사용하십시오. Threadtear는 크래킹 도구가 아닌 악성 코드 분석 툴킷을 목표로 합니다. 변환기가 제대로 작동하지 않으면 이슈를 열거나 이메일로 로그를 첨부하여 알려 주십시오. 출력 파일은 대부분 실행 가능하지 않을 수 있습니다. 그래도 실행하려면 JVM 인수로 -noverify를 사용하십시오! 이 도구는 Java 8과 함께 사용하도록 설계되었지만, 상위 버전에서도 실행될 수 있습니다.