
बहु-कार्यात्मक Java deobfuscation टूल सूट
Threadtear एक बहुक्रियाशील डीओबफस्केशन टूल है जो Java के लिए है। एंड्रॉइड एप्लिकेशन सपोर्ट जल्द ही आ रहा है (वर्तमान में एक डेल्विक से Java कन्वर्टर पर काम चल रहा है)।
ऑबफस्केशन के बारे में बहुत अधिक चिंता किए बिना कोड विश्लेषण को आसान बनाने के लिए उपयुक्त।
ZKM या Stringer जैसे सबसे महंगे ऑबफस्केटर भी शामिल हैं। आसान डिबगिंग के लिए अन्य टूल भी शामिल हैं।
एक्सेप्शन कहाँ से उत्पन्न होते हैं यह बेहतर समझने के लिए डीबग लाइन नंबर डालें, या कोड को पुनः संकलित किए बिना ट्राई-कैच ब्लॉक्स में .printStackTrace() जोड़ें।
रिवर्स संगतता अब कोई समस्या नहीं है, यदि संस्करण-विशिष्ट विधियों का उपयोग नहीं किया जाता है। ग्राफ़ में कोड प्रवाह का विश्लेषण करें, ताकि एल्गोरिदम को बेहतर ढंग से समझा जा सके।

एक "निष्पादन" एक कार्य है जो निष्पादित होता है और सभी लोडेड क्लास फ़ाइलों को संशोधित करता है। निष्पादन के कई प्रकार हैं, बाइटकोड क्लीनअप से लेकर स्ट्रिंग डीऑबफस्केशन तक। सुनिश्चित करें कि वे सही क्रम में हों। उदाहरण के लिए क्लीनअप निष्पादन को अंत में निष्पादित किया जाना चाहिए, लेकिन यदि पहले निष्पादित किया जाए तो यह अन्य निष्पादनों में भी मदद कर सकता है। यदि आप तैयार हैं, तो "Run" बटन पर क्लिक करें, और वे क्रम से निष्पादित होंगे।
इस टूल का उपयोग अपने जोखिम पर करें। कुछ निष्पादन JAR फ़ाइल से कोड चलाने के लिए कार्यान्वित ClassLoaders का उपयोग करते हैं। एक हमलावर बाइटकोड में इस तरह से बदलाव कर सकता है कि दुर्भावनापूर्ण कोड निष्पादित हो सके।
प्रभावित निष्पादन वर्ग 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 /* श्रेणी */, "My execution" /* नाम */,
"Executes something" /* विवरण, html का उपयोग कर सकते हैं */);
}
/**
* This method is invoked when the user clicks on the Run button
* @return true if success, false if failure
*/
@Override
public boolean execute(Map<String, Clazz> classes, boolean verbose) {
classes.values().stream().map(c -> c.node).forEach(c -> {
//transform the classes here using the tree-API of ASM
});
return false;
}
}
runtime पर ClassNodes लोड करने के लिए, 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);
//transform bytecode to java.lang.Class
Class<?> loadedClass = vm.loadClass(c.name.replace('/', '.'), true);
//do stuff with your class here
loadedClass.getMethods()[0].invoke(...);
return true;
});
}
/**
* Will get invoked by VM, when VM.loadClass is called
*/
@Override
public ClassNode tryClassLoad(String name) {
//try to find the class to be loaded in open jar archive
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 -> {
// this analyzer keeps known stack values, e.g. can be useful for jump prediction
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);