
मैलवेयर सुविधाओं का सिग्नेचर-आधारित पता लगाना जो विंडोज API कॉल अनुक्रमों पर आधारित है। यह सैंडबॉक्स API ट्रेस के लिए YARA की तरह है!
dynmx (उच्चारित dynamics) एक सिग्नेचर-आधारित पहचान दृष्टिकोण है जो विंडोज API कॉल अनुक्रमों पर आधारित बिहेवियरल मैलवेयर फीचर्स के लिए है। सरल शब्दों में, आप dynmx को API कॉल ट्रेस (जिन्हें फंक्शन लॉग कहा जाता है) के लिए एक प्रकार का YARA मान सकते हैं, जो मैलवेयर सैंडबॉक्स से उत्पन्न होते हैं। इसलिए, पहचान दृष्टिकोण का डेटा आधार स्थैतिक रूप से विश्लेषित मैलवेयर नमूने स्वयं नहीं हैं, बल्कि वह डेटा है जो मैलवेयर सैंडबॉक्स में मैलवेयर नमूने के गतिशील विश्लेषण के दौरान उत्पन्न होता है। वर्तमान में, dynmx निम्नलिखित मैलवेयर सैंडबॉक्स के फंक्शन लॉग का समर्थन करता है:
report.json फ़ाइल)report.json फ़ाइल)पहचान दृष्टिकोण का विस्तृत विवरण मास्टर थीसिस Signature-Based Detection of Behavioural Malware Features with Windows API Calls में दिया गया है। यह प्रोजेक्ट इस दृष्टिकोण का प्रोटोटाइप कार्यान्वयन है और मास्टर थीसिस के दौरान विकसित किया गया था। सिग्नेचर मैलवेयर विश्लेषकों द्वारा dynmx सिग्नेचर DSL में मैन्युअल रूप से परिभाषित किए जाते हैं और इस टूल की सहायता से फंक्शन लॉग में पहचाने जा सकते हैं। dynmx सिग्नेचर DSL की विशेषताएँ और सिंटैक्स भी मास्टर थीसिस में पाए जा सकते हैं। इसके अलावा, आप रिपॉजिटरी dynmx-signatures में नमूना dynmx सिग्नेचर पा सकते हैं। API कॉल के आधार पर मैलवेयर फीचर्स का पता लगाने के अलावा, dynmx मैलवेयर द्वारा उपयोग किए जाने वाले OS संसाधनों (एक तथाकथित Access Activity Model) को निकाल सकता है। ये संसाधन API कॉल की जांच करके और OS संसाधनों पर संचालन का पुनर्निर्माण करके निकाले जाते हैं। वर्तमान में, मॉडल में फाइल सिस्टम, रजिस्ट्री और नेटवर्क श्रेणियों के OS संसाधनों पर विचार किया जाता है।
निम्नलिखित अनुभाग में, मैलवेयर फीचर्स का पता लगाने और संसाधनों के निष्कर्षण के उदाहरण दिखाए गए हैं।
इस उदाहरण के लिए, हम SHA-256 हैश योग c0832b1008aa0fc828654f9762e37bda019080cbdd92bd2453a05cfb3b79abb3 वाला मैलवेयर नमूना चुनते हैं। के अनुसार MalwareBazaar, यह नमूना मैलवेयर परिवार Amadey से संबंधित है। इस नमूने का एक सार्वजनिक VMRay विश्लेषण रिपोर्ट उपलब्ध है जो VMRay द्वारा ट्रेस किया गया function log भी प्रदान करता है। यह फंक्शन लॉग हमारा डेटा आधार होगा जिसका उपयोग हम पहचान के लिए करेंगे। यदि हम जानना चाहते हैं कि मैलवेयर नमूना Process Hollowing नामक एक इंजेक्शन तकनीक का उपयोग करता है या नहीं, तो हम फंक्शन लॉग में निम्नलिखित dynmx सिग्नेचर का पता लगाने का प्रयास कर सकते हैं।```yaml
dynmx_signature:
meta:
name: process_hollow
title: Process Hollowing
description: Detection of Process hollowing malware feature
detection:
proc_hollow:
# Create legit process in suspended mode
- api_call: ["CreateProcess[AW]", "CreateProcessInternal[AW]"]
with:
- argument: "dwCreationFlags"
operation: "flag is set"
value: 0x4
- return_value: "return"
operation: "is not"
value: 0
store:
- name: "hProcess"
as: "proc_handle"
- name: "hThread"
as: "thread_handle"
# Injection of malicious code into memory of previously created process
- variant:
- path:
# Allocate memory with read, write, execute permission
- api_call: ["VirtualAllocEx", "VirtualAlloc", "(Nt|Zw)AllocateVirtualMemory"]
with:
- argument: ["hProcess", "ProcessHandle"]
operation: "is"
value: "$(proc_handle)"
- argument: ["flProtect", "Protect"]
operation: "is"
value: 0x40
- api_call: ["WriteProcessMemory"]
with:
- argument: "hProcess"
operation: "is"
value: "$(proc_handle)"
- api_call: ["SetThreadContext", "(Nt|Zw)SetContextThread"]
with:
- argument: "hThread"
operation: "is"
value: "$(thread_handle)"
- path:
# Map memory section with read, write, execute permission
- api_call: "(Nt|Zw)MapViewOfSection"
with:
- argument: "ProcessHandle"
operation: "is"
value: "$(proc_handle)"
- argument: "AccessProtection"
operation: "is"
value: 0x40
# Resume thread to run injected malicious code
- api_call: ["ResumeThread", "(Nt|Zw)ResumeThread"]
with:
- argument: ["hThread", "ThreadHandle"]
operation: "is"
value: "$(thread_handle)"
condition: proc_hollow as sequence
हस्ताक्षर के आधार पर, हम कुछ DSL विशेषताएँ पा सकते हैं जो *dynmx* को शक्तिशाली बनाती हैं:
* वैकल्पिक पथों के साथ API कॉल अनुक्रमों की परिभाषा
* रेगुलर एक्सप्रेशन के साथ API कॉल फंक्शन नामों का मिलान
* कई ऑपरेटरों के साथ तर्क और रिटर्न वैल्यू का मिलान
* चरों का भंडारण, उदा. API कॉल अनुक्रम में हैंडल को ट्रैक करने के लिए
* बूलियन ऑपरेटरों (`AND`, `OR`, `NOT`) के साथ एक डिटेक्शन शर्त की परिभाषा
यदि हम उपरोक्त दिखाए गए सिग्नेचर के साथ *dynmx* को नमूने `c0832b1008aa0fc828654f9762e37bda019080cbdd92bd2453a05cfb3b79abb3` के फंक्शन के विरुद्ध चलाते हैं, तो हमें निम्नलिखित आउटपुट मिलता है जो दर्शाता है कि सिग्नेचर का पता लगा लिया गया था।```
$ python3 dynmx.py detect -i 601941f00b194587c9e57c5fabaf1ef11596179bea007df9bdcdaa10f162cac9.json -s process_hollow.yml
|
__| _ _ _ _ _
/ | | | / |/ | / |/ |/ | /\/
\_/|_/ \_/|/ | |_/ | | |_/ /\_/
/|
\|
Ver. 0.5 (PoC), by 0x534a
[+] Parsing 1 function log(s)
[+] Loaded 1 dynmx signature(s)
[+] Starting detection process with 1 worker(s). This probably takes some time...
[+] Result
process_hollow c0832b1008aa0fc828654f9762e37bda019080cbdd92bd2453a05cfb3b79abb3.txt
हम अधिक विस्तार में जा सकते हैं आउटपुट फॉर्मेट को detail पर सेट करके। अब, हम फंक्शन लॉग में पाई गई सटीक API कॉल अनुक्रम देख सकते हैं। इसके अलावा, हम देख सकते हैं कि सिग्नेचर प्रक्रिया 51f0.exe में पाया गया।```
$ python3 dynmx.py -f detail detect -i 601941f00b194587c9e57c5fabaf1ef11596179bea007df9bdcdaa10f162cac9.json -s process_hollow.yml
|
__| _ _ _ _ _ / | | | / |/ | / |/ |/ | // _/|/ _/|/ | |/ | | |_/ /_/ /| |
Ver. 0.5 (PoC), by 0x534a
[+] Parsing 1 function log(s) [+] Loaded 1 dynmx signature(s) [+] Starting detection process with 1 worker(s). This probably takes some time...
[+] Result Function log: c0832b1008aa0fc828654f9762e37bda019080cbdd92bd2453a05cfb3b79abb3.txt Signature: process_hollow Process: 51f0.exe (PID: 3768) Number of Findings: 1 Finding 0 proc_hollow : API Call CreateProcessA (Function log line 20560, index 938) proc_hollow : API Call VirtualAllocEx (Function log line 20566, index 944) proc_hollow : API Call WriteProcessMemory (Function log line 20573, index 951) proc_hollow : API Call SetThreadContext (Function log line 20574, index 952) proc_hollow : API Call ResumeThread (Function log line 20575, index 953)
### Resources
फंक्शन लॉग से एक्सेस किए गए OS संसाधनों को निकालने के लिए, हम फंक्शन लॉग पर *dynmx* कमांड `resources` चला सकते हैं। नीचे SHA-256 हैश सम `601941f00b194587c9e57c5fabaf1ef11596179bea007df9bdcdaa10f162cac9` वाले नमूने के लिए विस्तृत आउटपुट का एक उदाहरण दिखाया गया है। यह एक CAPE सैंडबॉक्स रिपोर्ट है जो [Avast-CTU Public CAPEv2 Dataset](https://github.com/avast/avast-ctu-cape-dataset) का हिस्सा है।```
$ python3 dynmx.py -f detail resources --input 601941f00b194587c9e57c5fabaf1ef11596179bea007df9bdcdaa10f162cac9.json
|
__| _ _ _ _ _
/ | | | / |/ | / |/ |/ | /\/
\_/|_/ \_/|/ | |_/ | | |_/ /\_/
/|
\|
Ver. 0.5 (PoC), by 0x534a
[+] Parsing 1 function log(s)
[+] Processing function log(s) with the command 'resources'...
[+] Result
Function log: 601941f00b194587c9e57c5fabaf1ef11596179bea007df9bdcdaa10f162cac9.json (/Users/sijansen/Documents/dev/dynmx_flogs/cape/Public_Avast_CTU_CAPEv2_Dataset_Full/extracted/601941f00b194587c9e57c5fabaf1ef11596179bea007df9bdcdaa10f162cac9.json)
Process: 601941F00B194587C9E5.exe (PID: 2008)
Filesystem:
C:\Windows\SysWOW64\en-US\SETUPAPI.dll.mui (CREATE)
API-MS-Win-Core-LocalRegistry-L1-1-0.dll (EXECUTE)
C:\Windows\SysWOW64\ntdll.dll (READ)
USER32.dll (EXECUTE)
KERNEL32.dll (EXECUTE)
C:\Windows\Globalization\Sorting\sortdefault.nls (CREATE)
Registry:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\OLEAUT (READ)
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Setup (READ)
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Setup\SourcePath (READ)
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion (READ)
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\DevicePath (READ)
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Internet Settings (READ)
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Internet Settings\DisableImprovedZoneCheck (READ)
HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\CurrentVersion\Internet Settings (READ)
HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\Security_HKLM_only (READ)
Process: 601941F00B194587C9E5.exe (PID: 1800)
Filesystem:
C:\Windows\SysWOW64\en-US\SETUPAPI.dll.mui (CREATE)
API-MS-Win-Core-LocalRegistry-L1-1-0.dll (EXECUTE)
C:\Windows\SysWOW64\ntdll.dll (READ)
USER32.dll (EXECUTE)
KERNEL32.dll (EXECUTE)
[...]
C:\Users\comp\AppData\Local\vscmouse (READ)
C:\Users\comp\AppData\Local\vscmouse\vscmouse.exe:Zone.Identifier (DELETE)
Registry:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\OLEAUT (READ)
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Setup (READ)
[...]
Process: vscmouse.exe (PID: 900)
Filesystem:
C:\Windows\SysWOW64\en-US\SETUPAPI.dll.mui (CREATE)
API-MS-Win-Core-LocalRegistry-L1-1-0.dll (EXECUTE)
C:\Windows\SysWOW64\ntdll.dll (READ)
USER32.dll (EXECUTE)
KERNEL32.dll (EXECUTE)
C:\Windows\Globalization\Sorting\sortdefault.nls (CREATE)
Registry:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\OLEAUT (READ)
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Setup (READ)
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Setup\SourcePath (READ)
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion (READ)
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\DevicePath (READ)
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Internet Settings (READ)
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Internet Settings\DisableImprovedZoneCheck (READ)
HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\CurrentVersion\Internet Settings (READ)
HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\Security_HKLM_only (READ)
Process: vscmouse.exe (PID: 3036)
Filesystem:
C:\Windows\SysWOW64\en-US\SETUPAPI.dll.mui (CREATE)
API-MS-Win-Core-LocalRegistry-L1-1-0.dll (EXECUTE)
C:\Windows\SysWOW64\ntdll.dll (READ)
USER32.dll (EXECUTE)
KERNEL32.dll (EXECUTE)
C:\Windows\Globalization\Sorting\sortdefault.nls (CREATE)
C:\ (READ)
C:\Windows\System32\uxtheme.dll (EXECUTE)
dwmapi.dll (EXECUTE)
advapi32.dll (EXECUTE)
shell32.dll (EXECUTE)
C:\Users\comp\AppData\Local\vscmouse\vscmouse.exe (CREATE,READ)
C:\Users\comp\AppData\Local\iproppass\iproppass.exe (DELETE)
crypt32.dll (EXECUTE)
urlmon.dll (EXECUTE)
userenv.dll (EXECUTE)
wininet.dll (EXECUTE)
wtsapi32.dll (EXECUTE)
CRYPTSP.dll (EXECUTE)
CRYPTBASE.dll (EXECUTE)
ole32.dll (EXECUTE)
OLEAUT32.dll (EXECUTE)
C:\Windows\SysWOW64\oleaut32.dll (EXECUTE)
IPHLPAPI.DLL (EXECUTE)
DHCPCSVC.DLL (EXECUTE)
C:\Users\comp\AppData\Roaming\Microsoft\Network\Connections\Pbk\_hiddenPbk\ (CREATE)
C:\Users\comp\AppData\Roaming\Microsoft\Network\Connections\Pbk\_hiddenPbk\rasphone.pbk (CREATE,READ)
Registry:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\OLEAUT (READ)
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Setup (READ)
[...]
Network:
24.151.31.150:465 (READ)
http://24.151.31.150:465 (READ,WRITE)
107.10.49.252:80 (READ)
http://107.10.49.252:80 (READ,WRITE)
दिखाए गए आउटपुट और एक्सेस किए गए संसाधनों के आधार पर, हम कुछ मैलवेयर विशेषताओं का अनुमान लगा सकते हैं:
601941F00B194587C9E5.exe (PID 1800) के अंदर, फ़ाइल C:\Users\comp\AppData\Local\vscmouse\vscmouse.exe का ज़ोन आइडेंटिफ़ायर हटा दिया जाता हैvscmouse.exe (PID: 3036) नेटवर्क एंडपॉइंट्स http://24.151.31.150:465 और http://107.10.49.252:80 से कनेक्ट होती हैएक्सेस किए गए संसाधन होस्ट- और नेटवर्क-आधारित डिटेक्शन संकेतकों की पहचान करने के लिए दिलचस्प हैं। इसके अलावा, संसाधनों का उपयोग dynmx सिग्नेचर में किया जा सकता है। एक लोकप्रिय उदाहरण रजिस्ट्री में पर्सिस्टेंस तंत्र का पता लगाना है।``` dynmx_signature: meta: name: run_keys_persistence title: Run Keys Persistence description: Detection of persistence based on Registry Run Keys detection: run_keys: - resource: category: "registry" access_operations: ["write"] with: - attribute: "location" operation: "regex" value: "^(HKEY_CURRENT_USER|HKEY_LOCAL_MACHINE)\\Software\\Microsoft\\Windows\\CurrentVersion\\(Run|RunOnce|RunOnceEx)\\" startup_folders_keys: - resource: category: "registry" access_operations: ["write"] with: - attribute: "location" operation: "regex" value: "^(HKEY_CURRENT_USER|HKEY_LOCAL_MACHINE)\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\(Shell Folders|User Shell Folders)\\" condition: run_keys as simple or startup_folders_keys as simple
## स्थापना
सॉफ्टवेयर का उपयोग करने के लिए लक्ष्य प्रणाली पर Python 3.9 उपलब्ध होना चाहिए। इसके अतिरिक्त, निम्नलिखित Python पैकेज स्थापित करने की आवश्यकता है:
* `anytree`,
* `lxml`,
* `pyparsing`,
* `PyYAML`,
* `six` और
* `stringcase`
पैकेज स्थापित करने के लिए नीचे दिखाए गए `pip3` कमांड को चलाएँ। पैकेज को सिस्टम-वाइड स्थापित करने के बजाय Python वर्चुअल एनवायरनमेंट का उपयोग करने की अनुशंसा की जाती है।```
pip3 install -r requirements.txt
प्रोटोटाइप का उपयोग करने के लिए, बस मुख्य प्रवेश बिंदु dynmx.py चलाएँ। उपयोग जानकारी को -h कमांड लाइन पैरामीटर के साथ नीचे दिखाए अनुसार देखा जा सकता है।```
$ python3 dynmx.py -h
usage: dynmx.py [-h] [--format {overview,detail}] [--show-log] [--log LOG] [--log-level {debug,info,error}] [--worker N] {detect,check,convert,stats,resources} ...
Detect dynmx signatures in dynamic program execution information (function logs)
optional arguments: -h, --help show this help message and exit --format {overview,detail}, -f {overview,detail} Output format --show-log Show all log output on stdout --log LOG, -l LOG log file --log-level {debug,info,error} Log level (default: info) --worker N, -w N Number of workers to spawn (default: number of processors - 2)
sub-commands: task to perform
{detect,check,convert,stats,resources} detect Detects a dynmx signature check Checks the syntax of dynmx signature(s) convert Converts function logs to the dynmx generic function log format stats Statistics of function logs resources Resource activity derived from function log
सामान्यतः, जैसा कि आउटपुट में दिखाया गया है, लॉग हैंडलिंग, परिणामों के लिए आउटपुट प्रारूप या मल्टीप्रोसेसिंग से संबंधित कई कमांड लाइन पैरामीटर परिभाषित किए जा सकते हैं। इसके अलावा, एक विशिष्ट कार्य को चलाने के लिए एक कमांड चुनना आवश्यक है। कृपया ध्यान दें, कि वर्कर्स की संख्या केवल उन कमांडों को प्रभावित करती है जो मल्टीप्रोसेसिंग का उपयोग करते हैं। वर्तमान में, ये कमांड `detect` और `convert` हैं।
कमांड में विशिष्ट कमांड लाइन पैरामीटर होते हैं जिन्हें कमांड को `-h` पैरामीटर देकर खोजा जा सकता है, उदाहरण के लिए नीचे दिखाए गए अनुसार `detect` कमांड के लिए।```
$ python3 dynmx.py detect -h
usage: dynmx.py detect [-h] --sig SIG [SIG ...] --input INPUT [INPUT ...] [--recursive] [--json-result JSON_RESULT] [--runtime-result RUNTIME_RESULT] [--detect-all]
optional arguments:
-h, --help show this help message and exit
--recursive, -r Search for input files recursively
--json-result JSON_RESULT
JSON formatted result file
--runtime-result RUNTIME_RESULT
Runtime statistics file formatted in CSV
--detect-all Detect signature in all processes and do not stop after the first detection
required arguments:
--sig SIG [SIG ...], -s SIG [SIG ...]
dynmx signature(s) to detect
--input INPUT [INPUT ...], -i INPUT [INPUT ...]
Input files
dynmx के उपयोगकर्ता के रूप में, आप यह तय कर सकते हैं कि आउटपुट कैसे संरचित हो। यदि आप पैरामीटर --show-log को परिभाषित करके कंसोल पर लॉग दिखाना चुनते हैं, तो आउटपुट में दो खंड होते हैं (नीचे सूची देखें)। पहले लॉग दिखाया जाता है और उसके बाद उपयोग की गई कमांड के परिणाम। डिफ़ॉल्ट रूप से, लॉग न तो कंसोल में दिखाया जाता है और न ही किसी लॉग फ़ाइल में लिखा जाता है (जिसे --log पैरामीटर का उपयोग करके परिभाषित किया जा सकता है)। मल्टीप्रोसेसिंग के कारण, लॉग फ़ाइल में प्रविष्टियाँ आवश्यक रूप से कालानुक्रमिक क्रम में नहीं होती हैं।```
|
__| _ _ _ _ _ / | | | / |/ | / |/ |/ | // _/|/ _/|/ | |/ | | |_/ /_/ /| |
Ver. 0.5 (PoC), by 0x534a
[+] Log output 2023-06-27 19:07:38,068+0000 [INFO] (main) [PID: 13315] []: Start of dynmx run [...] [+] End of log output
[+] Result [...]
परिणाम आउटपुट के विवरण स्तर को कमांड लाइन पैरामीटर `--output-format` का उपयोग करके परिभाषित किया जा सकता है, जिसे उच्च-स्तरीय परिणाम के लिए `overview` या विस्तृत परिणाम के लिए `detail` पर सेट किया जा सकता है। उदाहरण के लिए, यदि आप आउटपुट प्रारूप को `detail` पर सेट करते हैं, तो कंसोल में दिखाए गए डिटेक्शन परिणामों में वे सटीक API कॉल और संसाधन शामिल होंगे जिनके कारण डिटेक्शन हुआ। `overview` आउटपुट प्रारूप केवल यह इंगित करेगा कि किस फ़ंक्शन लॉग में कौन सा सिग्नेचर डिटेक्ट हुआ।
## उदाहरण कमांड लाइन
एक वर्कर प्रक्रिया के साथ फ़ंक्शन लॉग में एक *dynmx* सिग्नेचर का डिटेक्शन```
python3 dynmx.py -w 1 detect -i "flog.txt" -s dynmx_signature.yml
एक फंक्शन लॉग का dynmx सामान्य फंक्शन लॉग प्रारूप में रूपांतरण``` python3 dynmx.py convert -i "flog.txt" -o /tmp/
हस्ताक्षर की जाँच करें (केवल बुनियादी सत्यापन)```
python3 dynmx.py check -s dynmx_signature.yml
एक मैलवेयर नमूने द्वारा उपयोग किए गए संसाधनों की विस्तृत सूची प्राप्त करें जो फंक्शन लॉग (एक्सेस एक्टिविटी मॉडल) पर आधारित हो।``` python3 dynmx.py -f detail resources -i "flog.txt"
## समस्या निवारण
कृपया ध्यान रखें कि यह टूल एक प्रूफ-ऑफ-कॉन्सेप्ट है जिसे मास्टर थीसिस लिखने के साथ-साथ विकसित किया गया था। इसलिए, कोड की गुणवत्ता हमेशा सर्वोत्तम नहीं होती है और इसमें बग्स और त्रुटियाँ हो सकती हैं। मैंने दिए गए समय सीमा में टूल को यथासंभव मजबूत बनाने का प्रयास किया है।
त्रुटियों के समस्या निवारण का सबसे अच्छा तरीका लॉगिंग को सक्षम करना (कंसोल और/या लॉग फ़ाइल पर) और लॉग स्तर को `debug` पर सेट करना है। अपवाद हैंडलर को लॉग में विस्तृत त्रुटियाँ लिखनी चाहिए जो समस्या निवारण में मदद कर सकती हैं।