
VBScript और VBA स्रोत-से-स्रोत डीऑबफस्केटर जिसमें आंशिक-मूल्यांकन शामिल है
vbSparkle एक स्रोत-से-स्रोत (source-to-source) मल्टी-प्लेटफ़ॉर्म Visual Basic डिओबफसकेटर है जो आंशिक-मूल्यांकन (partial-evaluation) पर आधारित है और मुख्य रूप से VBScript और VBA (Office Macro) में लिखे दुर्भावनापूर्ण कोड के विश्लेषण के लिए समर्पित है।
यह नेटिव C# में लिखा गया है और एक .Net Standard लाइब्रेरी प्रदान करता है, तथा Windows, Linux, MacOS आदि पर काम करता है।
Visual Basic Script और VBA का पार्सिंग ANTLR व्याकरण (grammar) और लेक्सर पार्सर के उपयोग से की जाती है।
Install-Package vbSparkle
dotnet add package vbSparkle
एक बार जब आप अपने प्रोजेक्ट में vbSparkle लाइब्रेरी जोड़ लेते हैं, तो आपको केवल स्थिर वर्ग VbPartialEvaluator से फ़ंक्शन PrettifyEncoded को कॉल करना होता है:
string obfuscatedVB = "msgbox(chr(65)&chr(66)&(chr(67))"
string deobfuscated = VbPartialEvaluator.PrettifyEncoded(obfuscatedVB);
... यह MsgBox("ABC") लौटाएगा।
संलग्न प्रोजेक्ट vbSparkle.CLI, vbSparkle को CLI के रूप में उपयोग करने का एक उदाहरण है।
वर्तमान उदाहरण या तो एक तर्क के रूप में पथ लेता है या StdIn में पूरा बाइनरी लेता है, और डिओबफसकेटेड परिणाम लौटाता है।

संलग्न प्रोजेक्ट vbSparkle.Web, वेब UI के भीतर vbSparkle के उपयोग का एक उदाहरण है।

VBScript और VBA कोड ऑबफसकेशन हमलावरों के बीच लोकप्रिय है और यह पहचान उपायों, एंटीवायरस, फ़ायरवॉल, EDRs को बायपास करने की अनुमति देता है, तथा मैलवेयर विश्लेषण को अधिक कठिन बनाता है।
इस प्रकार मशीन से छेड़छाड़ (compromission) के पहले चरण में ऑबफसकेटेड VBScript देखना आम बात है।
एक विशिष्ट VBScript कोड ऑबफसकेशन तकनीक स्क्रिप्ट को एक ऑबफसकेटेड स्ट्रिंग में संलग्न करना है और उसे डीकोड / मूल्यांकन किए जाने के बाद Execute("...code..." function) के माध्यम से निष्पादित करना है।
आइए एक उदाहरण देखें:
Execute(chr( 456127/3833 ) & chr( 817650/7110 ) & chr( 759429/7671 ) & chr( 834138/7317 ) & chr( 57960/552 ) & chr( 2549-2437 ) & chr( 1078568/9298 ) & chr( 5143-5097 ) & chr( -8682+8783 ) & chr( 529-430 ) & chr( 673088/6472 ) & chr( 761682/6862 ) & chr( 302336/9448 ) & chr( 9427-9393 ) & chr( 410176/3944 ) & chr( -5271+5372 ) & chr( 796608/7376 ) & chr( 2896-2788 ) & chr( 318792/2872 ) & chr( 1076-1042 ) & vbcrlf )
यहाँ, हमलावर ने उपयोग किया है:
chr(CHAR_CODE) फ़ंक्शन (जैसे chr(65) = "A")456127/3833)&Execute(..) फ़ंक्शन का कॉल।यदि हम स्क्रिप्ट निष्पादन का अनुसरण करें:
456127/3833 => 119chr(119) => "w"817650/7110 => 115chr(115) => "s""w" & "s" => "ws"Execute("ws.....यहाँ मूल स्क्रिप्ट है:
wscript.echo "hello"
मैन्युअल डिओबफसकेशन बड़ी स्क्रिप्ट पर बहुत कठिन और समय लेने वाला हो जाता है।
VBScript के साथ एक सामान्य डिओबफसकेशन तकनीक केवल Execute() फ़ंक्शन को WScript.Echo( से बदलना है, और फिर आउटपुट प्राप्त करने के लिए स्क्रिप्ट चलाना है।
यह अंतिम तकनीक सरल है लेकिन इसके कुछ नुकसान हैं:
और, जब यह प्रोजेक्ट शुरू हुआ था, इन दोनों तकनीकों का कोई विकल्प नहीं था।
आंशिक-मूल्यांकन कोई नई अवधारणा नहीं है, यह मुख्य रूप से कंपाइलरों द्वारा प्री-कंपाइलेशन प्रक्रिया में कोड-अनुकूलन के लिए उपयोग किया जाता है (जैसे https://en.wikipedia.org/wiki/Partial_evaluation)।
एक आंशिक मूल्यांकनकर्ता एक प्रोग्राम (जिसे विषय प्रोग्राम कहा जाता है) को उस प्रोग्राम के कुछ इनपुट के साथ पढ़ता है, और प्रोग्राम के केवल उन हिस्सों का मूल्यांकन करता है जो प्रदान किए गए इनपुट पर निर्भर करते हैं। एक बार इन सभी भागों का मूल्यांकन हो जाने के बाद, शेष प्रोग्राम (जिसे अवशिष्ट प्रोग्राम कहा जाता है) आउटपुट के रूप में जारी किया जाता है।
उदाहरण के लिए, एक प्री-कंपाइलेशन प्रक्रिया निम्नलिखित विषय कोड को रूपांतरित करेगी:
var1 = 3*3
var2 = sin(arg1)
var3 = var1 + func_xx(2 * var1 + var2)
निम्नलिखित अवशिष्ट कोड में:
var2 = sin(arg1)
var3 = 9 + func_xx(18 + var2)
प्रदर्शन को अनुकूलित करने के लिए कोड का कंपाइलेशन से पहले आंशिक रूप से मूल्यांकन किया गया है।
हम देखते हैं कि यह प्रक्रिया कोड को सरल बनाती है, और अनावश्यक संक्रियाओं को समाप्त करती है। यह दिलचस्प है क्योंकि ऑबफसकेशन कोड के निष्पादन के लिए अनावश्यक कोड और संक्रियाएँ जोड़कर कोड को छिपाता है।
यदि हम अपने प्रारंभिक नमूने का चरण-दर-चरण निरीक्षण करें:
456127/3833 आंशिक रूप से मूल्यांकित की जा सकती है: कोई दुष्प्रभाव नहींchr(119) आंशिक रूप से मूल्यांकित किया जा सकता है: 119 एक स्थिरांक है, और यह एक मूल फ़ंक्शन है, कोई दुष्प्रभाव नहींउस नमूने का आंशिक मूल्यांकन इसका परिणाम देगा:
Execute("wscript.echo ""hello""" & vbCrLf)
और अंदाज़ा लगाइए क्या? ओह, हमने अभी अपने नमूने को डिओबफसकेट कर दिया।
खैर, व्यवहार में, यह कहीं अधिक जटिल है:
उम्मीद है, ANTLR संरचित पाठ या बाइनरी फ़ाइलों को पढ़ने, संसाधित करने, निष्पादित करने या अनुवाद करने के लिए एक शक्तिशाली पार्सर जनरेटर है। यह भाषाओं, उपकरणों और फ्रेमवर्क के निर्माण के लिए व्यापक रूप से उपयोग किया जाता है। एक व्याकरण से, ANTLR एक पार्सर उत्पन्न करता है जो पार्स ट्री बना सकता है और एक लिस्नर इंटरफ़ेस (या विज़िटर) भी उत्पन्न करता है जो रुचि के वाक्यांशों की पहचान का जवाब देना आसान बनाता है।
ANTLR लेक्सर्स, पार्सर्स, ट्री पार्सर्स और संयुक्त लेक्सर-पार्सर्स उत्पन्न कर सकता है। पार्सर्स स्वचालित रूप से पार्स ट्री या अमूर्त सिंटैक्स ट्री उत्पन्न कर सकते हैं जिन्हें ट्री पार्सर्स के साथ आगे संसाधित किया जा सकता है। ANTLR लेक्सर्स, पार्सर्स और ट्री पार्सर्स को निर्दिष्ट करने के लिए एक सुसंगत संकेतन प्रदान करता है।
डिफ़ॉल्ट रूप से, ANTLR एक व्याकरण पढ़ता है और व्याकरण द्वारा परिभाषित भाषा के लिए एक पहचानकर्ता (recognizer) उत्पन्न करता है (अर्थात, एक प्रोग्राम जो इनपुट स्ट्रीम पढ़ता है और यदि इनपुट स्ट्रीम व्याकरण द्वारा निर्दिष्ट सिंटैक्स के अनुरूप नहीं है तो त्रुटि उत्पन्न करता है)।
भाषा के साथ कुछ उपयोगी करने के लिए, व्याकरण में व्याकरण तत्वों से क्रियाएँ (actions) जोड़ी जा सकती हैं। ये क्रियाएँ उस प्रोग्रामिंग भाषा में लिखी जाती हैं जिसमें पहचानकर्ता उत्पन्न किया जा रहा है। जब पहचानकर्ता उत्पन्न किया जा रहा होता है, तो क्रियाएँ उपयुक्त बिंदुओं पर पहचानकर्ता के स्रोत कोड में एम्बेड की जाती हैं।
ANTLR के लिए धन्यवाद, Ulrich Wolffgang द्वारा लिखित मौजूदा व्याकरण की बदौलत AST, लेक्सर और पार्सर का पहला संस्करण उत्पन्न करना तेज़ और आसान था।
VB व्याकरण से Railroad नमूना:

यह व्याकरण कुछ विशिष्ट Visual Basic सिंटैक्स (इनलाइन कोड, कुछ ऑपरेटर समस्याएँ) के साथ पूरी तरह से काम नहीं कर रहा था और पूर्ण VBS और VBA संगत व्याकरण प्रदान करने के लिए कुछ बदलाव आवश्यक थे। संशोधित व्याकरण यहाँ पाया जा सकता है: Visual Basic Grammar
निम्नलिखित कोड के दृश्य पार्स ट्री का एक उदाहरण यहाँ है:
Msgbox("Hello world " & Chr(33), vbCritical, "The Title")

एक बार पार्सर और AST उत्पन्न हो जाने के बाद, हम इसका उपयोग शुरू कर सकते हैं और अपने कोड का अन्वेषण कर सकते हैं:
using Antlr4.Runtime;
using System.Linq;
namespace vbSparkle
{
public class PartialEvaluator
{
public static string Prettify(string script)
{
var inputStream = new AntlrInputStream(script);
// Create the lexer
var lexer = new VBScriptLexer(inputStream);
// Instanciate of common token from lexer
var commonTokenStream = new CommonTokenStream(lexer);
// Create the parser
var parser = new VBScriptParser(commonTokenStream);
// Get the start rule (root element of our AST)
VBScriptParser.StartRuleContext stContext = parser.startRule();
// Instanciate the visitor
VbAnalyser analyser = new VbAnalyser();
// Visit the AST
analyser.Visit(stContext);
// Root AST element of a vbScript being a "Module", we get it
var module = analyser.Modules.FirstOrDefault();
// Then we partially evaluate our module
string result = module.Prettify(partialEvaluation: true);
return result;
}
}
}
एक विज़िटर AST को पार करने और प्रत्येक नोड के लिए आंशिक-मूल्यांकनकर्ता/प्रेटिफायर बनाने के लिए जिम्मेदार है।
ये अंतिम नोड पुनरावर्ती रूप से मूल्यांकन करने के लिए जिम्मेदार होंगे:

उदाहरण के लिए, यहाँ हमारा विज़िटर है, जो एक VbModule मूल्यांकनकर्ता को इंस्टेंशिएट करता है:
public class VbAnalyser
{
public List<VbModule> Modules { get; set; } = new List<VbModule>();
internal void Visit(VBScriptParser.StartRuleContext stContext)
{
var moduleContext = stContext.module();
VbModule module = new VbModule(this, moduleContext);
Modules.Add(module);
}
}
यहाँ Prettify फ़ंक्शन वाले नोड का एक उदाहरण है:
public class VbOnGotoStatement : VbStatement<VBScriptParser.OnGoToStmtContext>
{
public VBValueStatement OnValue { get; set; }
public VBValueStatement[] GotoValues { get; set; }
public VbOnGotoStatement(IVBScopeObject context, VBScriptParser.OnGoToStmtContext bloc)
: base(context, bloc)
{
OnValue = VBValueStatement.Get(context, bloc.valueStmt().First());
GotoValues = bloc.valueStmt().Skip(1).Select(v => VBValueStatement.Get(context, v)).ToArray();
}
public override DExpression Prettify(bool partialEvaluation = false)
{
return new DCodeBlock($"On {OnValue.Prettify(partialEvaluation)} Goto {string.Join(", ", GotoValues.Select(v=> v.Prettify(partialEvaluation)))}");
}
}
जब नोड को कंस्ट्रक्टर VbOnGotoStatement( के माध्यम से विज़िट किया जाता है, तो यह पुनरावर्ती रूप से उप-नोड्स को विज़िट करता है और उनके स्वयं के विज़िटरों के उदाहरण बनाता है।
फिर, जब Prettify विधि कहा जाता है, उप-तत्वों को समान आंशिक मूल्यांकन स्तर के साथ प्रेटिफाई किया जाता है।