
مجموعة من التقنيات والأمثلة والقليل من النظريّة لإخفاء سكربتات PowerShell يدويًا لتحقيق التهرب من برامج مكافحة الفيروسات، جُمّعت لأغراض تعليمية. محتويات هذا المستودع هي نتيجة بحث شخصي، بما في ذلك قراءة مواد عبر الإنترنت وإجراء محاولات تجربة وخطأ في المختبرات واختبارات الاختراق.
مجموعة من التقنيات والأمثلة والقليل من النظري لإخفاء سكربتات PowerShell يدويًا لتجاوز الكشف القائم على التوقيعات (signature-based detection)، جُمعت لأغراض تعليمية. محتويات هذا المستودع هي نتيجة بحث شخصي، بما في ذلك قراءة مواد على الإنترنت وإجراء محاولات تجربة وخطأ في المختبرات واختبارات الاختراق. لا ينبغي أن تأخذ أي شيء كأمر مسلّم به.
عرض فيديو على يوتيوب: youtube.com/watch?v=tGFdmAh_lXE
⚠️ إخلاء مسؤولية: استخدام التقنيات والمفاهيم الموصوفة في هذا المستودع للوصول غير المصرح به إلى أنظمة ليس لديك الإذن باختبارها هو أمر غير قانوني. أنت مسؤول عن أفعالك. لا تكن شريرًا.
المصطلح العلمي entropy، الذي يُعرَّف عمومًا بأنه مقياس العشوائية أو الاضطراب في نظام ما، مهم في التهرب من برامج مكافحة الفيروسات (AV). وذلك لأن البرمجيات الخبيثة غالبًا ما تحتوي على كود عشوائي للغاية ومشفّر و/أو مُرمَّز (مُخفى) لجعل تحليله وبالتالي اكتشافه أمرًا صعبًا. تستخدم منتجات مكافحة الفيروسات، ضمن طرق متعددة، تحليل الإنتروبيا لتحديد الملفات والحمولات (payloads) التي يحتمل أن تكون خبيثة.
من المهم فهم هذا المفهوم لأنه عند إخفاء الكود، يجب أن تضع في اعتبارك تباين الإنتروبيا الناتج عن التغييرات التي تختار إجراءها. كسر التوقيعات سهل، لكن إذا لم تنتبه إلى مستوى الإنتروبيا، فستكتشف أنظمة AV/EDR المتطورة الأمر.
مبدأ يجب وضعه في الاعتبار: كلما زادت الإنتروبيا، زاد احتمال أن تكون البيانات مخفية أو مشفرة، وزاد احتمال أن يكون الملف/الحمولة خبيثًا. لحسن الحظ، هناك طرق لخفضها.
قدّم Claude E. Shannon معادلة في ورقته البحثية عام 1948 A Mathematical Theory of Communication يمكن استخدامها لقياس الإنتروبيا في مجموعة بيانات. إليك تنفيذ بسيط بلغة Python لمقياس Shannon Entropy يمكنك استخدامه لقياس إنتروبيا الحمولات التي تطورها:
#!/bin/python3
# Usage: python3 entropy.py <file>
import math, sys
def entropy(string):
"Calculates the Shannon entropy of a UTF-8 encoded string"
# decode the string as UTF-8
unicode_string = string.decode('utf-8')
# get probability of chars in string
prob = [ float(unicode_string.count(c)) / len(unicode_string) for c in dict.fromkeys(list(unicode_string)) ]
# calculate the entropy
entropy = - sum([ p * math.log(p) / math.log(2.0) for p in prob ])
return entropy
f = open(sys.argv[1], 'rb')
content = f.read()
f.close()
print(entropy(content))
يمكنك أيضًا استخدام حاسبة Shannon Entropy عبر الإنترنت، أو أداة Sigcheck.exe من Microsoft مع الخيار -a.
الأمر الناضج والأنيق قبل الانطلاق في اختبارات إخفاء قائمة على التجربة والخطأ للتوصل إلى صيغة حمولة لا يتم الإبلاغ عنها، هو تحديد الجزء أو الأجزاء في السكربت التي تحفز اكتشاف البرمجيات الخبيثة. خاصة في السكربتات القصيرة مثل أوامر C2، قد تتمكن من إجراء تغييرات طفيفة وتختفي من الرادار فورًا.
أداة رائعة لتحديد مثل هذه المشغلات هي AMSITrigger. إليك مثال استخدام مع ملف يحتوي على سكربت خبيث. المنطقة الحمراء تشير إلى الجزء الذي يجب تطبيق الإخفاء عليه:

يمكنك أيضًا تحديد المشغلات يدويًا عن طريق تنفيذ السكربت جزءًا جزءًا.
عند إخفاء السكربتات، يجب أن تكون أولوية استبدال أسماء المتغيرات/الأصناف/الدوال بأسماء عشوائية. بهذه الطريقة، وبالاقتران مع تقنيات أخرى، ستتمكن من تجاوز الكشف بسهولة. لكن يجب أن تضع في اعتبارك الإنتروبيا للحمولات التي تطورها. لاحظ سكربت الـ reverse shell القياسي التالي الذي يتم اكتشافه عمومًا بواسطة معظم إن لم يكن كل برامج مكافحة الفيروسات:

الآن لاحظ النسخة المخفية التالية:

في هذه النسخة، استُبدلت جميع أسماء المتغيرات بأسماء عشوائية بطول 32 محرفًا. كما استبدلت (pwd).Path بـ $(gl). الحمولة لديها Shannon entropy تبلغ 4.96. وقت كتابة هذا، لا يتم اكتشافها بواسطة MS Defender ومجموعة من المنتجات الأخرى:

الآن لاحظ هذه النسخة:

هذه النسخة أيضًا استُبدلت فيها جميع أسماء المتغيرات، لكن هذه المرة بأسماء تتكون من عدد x من محارف 'f'، مما يؤدي إلى انخفاض كبير في إنتروبيا الحمولة. كما استبدلت (pwd).Path بـ $(gl) هنا أيضًا. ومرة أخرى، وقت كتابة هذا، لا يتم اكتشافها بواسطة MS Defender. الحمولة لديها Shannon entropy تبلغ 0.76.

⚡ كلتا النسختين تتجاوزان برامج مكافحة الفيروسات الشائعة، لكن النسخة الثانية لديها إنتروبيا أقل وستحظى على الأرجح بفرصة أفضل عند معالجتها بواسطة أنظمة EDR ومحركات مكافحة البرمجيات الخبيثة المتطورة الأخرى. ⚠️ أنا لا أقول إن الأداء الأفضل للنسخة الثانية من الحمولة في هذا المثال يعود بالتأكيد إلى مستوى الإنتروبيا (لا يمكنني معرفة ذلك فعلًا، فقد يكون السبب هو الطول أو كلاهما أو من يعلم ماذا)، لكنه جانب مهم يجب وضعه في الاعتبار عند إخفاء الأشياء، وهذا المثال يهدف إلى توضيح هذا المفهوم.
يمكنك استخدام السكربت أدناه لعشوائية أسماء المتغيرات في سكربت PowerShell. ⚠️ السكربت ليس مثاليًا! إذا شغّلته على سكربتات PowerShell كبيرة ومعقدة فقد يكسر وظائفها عن طريق استبدال أشياء لا ينبغي استبدالها. استخدمه بحذر وكن منتبهًا.
#!/bin/python3
#
# This script is an example. It is not perfect and you should use it with caution.
# Source: https://github.com/t3l3machus/PowerShell-Obfuscation-Bible
# Usage: python3 randomize-variables.py <path/to/powershell/script>
import re
from sys import argv
from uuid import uuid4
def get_file_content(path):
f = open(path, 'r')
content = f.read()
f.close()
return content
def main():
payload = get_file_content(argv[1])
used_var_names = []
# Identify variables definitions in script
variable_definitions = re.findall('\$[a-zA-Z0-9_]*[\ ]{0,}=', payload)
variable_definitions.sort(key=len)
variable_definitions.reverse()
# Replace variable names
for var in variable_definitions:
var = var.strip("\n \r\t=")
while True:
new_var_name = uuid4().hex
if (new_var_name in used_var_names) or (re.search(new_var_name, payload)):
continue
else:
used_var_names.append(new_var_name)
break
payload = payload.replace(var, f'${new_var_name}')
print(payload + '\n')
main()