-
تعداد ارسال ها
10 -
تاریخ عضویت
-
روز های برد
9
پست ها ارسال شده توسط سید عمید قائم مقامی
-
-
قسمت اول:Block Environment Block (PEB) از زمان معرفی Win2k (ویندوز 2000) در ویندوز وجود داشته است و از آن زمان به بعد نسخه های جدیدتر ویندوز بهبود یافته است. در نسخه های قبلی ویندوز ، انجام برخی کارهای ناخوشایند مانند پنهان کردن ماژول های بارگذاری شده موجود در یک فرآیند (برای جلوگیری از پیدا شدن آنها - بدیهی است که این چیز زیبایی نیست) سوءاستفاده می شود.
چرا این موضوع مهم را “Process Environment (PEB)” مینامیم؟ PEB ساختاری است که اطلاعات مربوط به روند فعلی را تحت مقادیر خود نگهداری می کند - برخی از زمینه ها (فیلد ها یا داده ها) خود ساختارهایی هستند که حتی داده های بیشتری را در خود جای می دهند. هر فرآیندی PEB خاص خود را دارد و هسته Windows نیز به PEB هر فرآیند حالت کاربر دسترسی دارد تا بتواند داده های ذخیره شده در آن را پیگیری کند.این ساختار از کجا می آید؟ ساختار PEB از هسته ویندوز ناشی می شود (اگرچه در حالت کاربر نیز قابل دسترسی است). PEB از Block Environment Thread (TEB) ناشی می شود که معمولاً به آن Thread Information Block (TIB) نیز گفته می شود. TEB مسئول نگهداری اطلاعات مربوط به thread فعلی است - هر thread ساختار TEB خاص خود را دارد.آیا می توان از Block Environment Block یا Block Environment Block برای اهداف مخرب سوء استفاده کرد؟ البته آنها می توانند! در واقع ، آنها در گذشته برای اهداف مخرب مورد سوء استفاده قرار گرفته اند ، اما مایکروسافت طی سالهای اخیر تغییرات زیادی را برای جلوگیری از این امر انجام داده است. مثالی در گذشته بود که روت کیت ها یک DLL را به یک فرایند در حال اجرا تزریق می کردند و سپس به ساختار PEB فرآیند فعلی که به آن تزریق کرده بودند دسترسی پیدا می کردند (ساختار PPEB اشاره گر به ساختار PEB است) تا بتوانند لیست را پیدا کنند. از ماژول های بارگذاری شده و ماژول خود را از لیست حذف کنید ... بنابراین هنگامی که کسی ماژول های بارگذاری شده فرآیند آسیب دیده را برشمارد ، ماژول تزریق شده را از نظر پنهان می کند. این به عنوان وصله حافظه شناخته می شود زیرا شما می توانید با وصله PEB حافظه را تغییر دهید. تلاش مایکروسافت برای این کاهش رفتار این بود که از تغییر دستی لیست که نشان دهنده ماژول های بارگذاری شده در حالت کاربر است جلوگیری کند-شما همچنان می توانید برای خواندن داده ها در حالت کاربر به آن دسترسی داشته باشید و همچنان می توانید حافظه را از حالت کرنل وصله کنید.پایان قسمت اول
- 1
- 1
-
Windows Access Control List (ACL)
قسمت سوم (مفاهیم)
مباحث مورد بررسی در این مقاله:
- Win32 Object
- Account
- Security Identifier (SID)
- Access Control Entries (AEC)
- Access Control List (ACL)
- Discretionary Access Control List (DACL)
- System Access Control List (SACL)
- Security Desctiptors (SD)
Win32 Objects:
سیستم عامل ویندوز قادر به ایجاد چندین نوع مختلف از اشیاء Win32 است. این اشیائ به گونه ای هستند که دارای حافظه می باشند. نمونه هایی از این اشیاء عبارتند از:
Files
Directories
Registry keys
Network shares
Printer shares
Semaphores
Mutexes
Process tokensو ....
ماهیت این اشیاء به نوعی است که سیستم عامل می تواند آنها را در هر حافظه ای ذخیره کند (مانند رم، فلاپی، هارد دیسک، ذخیره در درایو شبکه، انتقال آن به دیگر کامپیوتر های روی شبکه).
به عنوان مثال، فایل یک شئ از سیستم عامل می باشد. زمانی که شما یک فایل می سازید(مثلا یک فایل Microsoft word) سیستم عامل با آن به عنوان یک شئ برخورد می کند. حتی ممکن است بخواهید که فایل را داخل یک درایو ذخیره کنید تا بعدا به آن دسترسی داشته باشید. برای سیستم عامل مهم نیست که شما می خواهید شئ را در یک درایو ذخیره کنید یا نه، تنها این موضوع را می داند (اهمیت می دهد) که آن شئ مقداری از فضا را اشغال می کند (چه در رم یا جای دیگر).
شئ پایدار (persistent object) شئی است که در دستگاه های حافظه بلند مدت ذخیره می شوند (مانند هارد دیسک) به گونه ای که داده ها بعدا قابل بازیابی باشند(ارساله داده به کارت صدا یا چاپگر باعث ایجاد شئ پایدار نمی شود، زیرا سیستم عامل بعدا قادر به بازیابی داده های آن نمی باشد).
Win32 سیستم عامل به طور معمول در روز ده ها هزار شئ را مدیریت می کند. Win32 سیستم عامل تقریبا فقط یک مدیر اجرائی پیچیده به حساب می آید (object manager). از آنجایی که سیستم عامل با اشیاء در ارتباط است میداند که مواقعی وجود دارد که اشیائ باید ایمن شوند. مثلا زمان ذخیره یک پرونده حساس در یک هارد درایو، باید از کاربران غیر مجاز حفظ شود.
Securing Objects:
Win32، مکانیزمی را برای تامین امنیت انواع متفاوتی از اشیاء فراهم کرده است. به بیان ساده تر، تامین امنیت یک شئ به این معنی است که مجموعه ای از مجوز ها ایجاد شود که با شئ مورد نظر مرتبط باشد. هر شئ می تواند برای خو یک سری مجوز ها داشته باشد.
Accounts:
در قلب سیستم امنیتی Win32 همان چیزی است که به عنوان حساب کاربری (account) شناخته می شود. این همان چیزی است که فرد هنگام ورود به سیستم می تواند مشخص کند، و این به عنوان user account شناخته می شود. User account از یک نام شناسایی (Userid)، یک رمز عبور و یک دسته اطلاعات دیگر که فقط مربوط به آن کاربر خاص است، شامل می شود.
انواع دیگری از حساب های کاربری وجود دارد. این حساب ها مانند حساب کاربری هستند به جز اینکه آنها کاربری را معرفی نمی کنند، بلکه انواع دیگری از حساب را معرفی می کنند. انواع حساب های کاربری عبارتند از:
- User accounts
- Machine accounts
- Domain accounts
- Group accounts
حساب های user ،machine و domain همه دارای رمزعبور هستند. رمز ورود یک حساب کاربری به طور خودکار توسط Primary Domain Controller (PDC) و دستگاه مدیریت می شود.
آخرین حساب، حساب group account می باشد. برخلاف حساب های دیگر، این حساب رمز عبور ندارد. دو نوع مختلف از حساب های گروهی وجود دارد:
Local group و global group.
تفاوت این دو فراتر از محدوده این مقاله می باشد، اما باید این را بدانید که حساب کاربریی وجود دارد که فاقد رمز عبور است.به طور معمول حساب های کاربری دارای نام هایی مانند زیر هستند:
- Administrator
- Guest
- Joel
Group accounts نام هایی مانند نام های زیر دارند:
- Guests
- Domain Admins
- Managers
چندین حساب سیستم وجود دارد که نمی توان آنها را مدیریت کرد و دارای معانی ویژه ای هستند:
- Everyone (all users)
- CREATOR OWNER (the owner and creator of a given object)
- SYSTEM (the Win32 system kernel)
نکته دیگر اینکه اگر به یک حساب کاربری در یک دامنه دیگر اشاره می کنید، می توانید نام دامنه و backslash را به نام حساب اضافه کنید:
- Roth Consulting\Joel
- Roth Consulting\Domain Admins
- Microsoft\Gates
- Accounting\Managers
دو دامنه از پیش تعریف شده وجود دارد که قابل اصلاح یا تغییر نیستند و دارای معانی خاصی هستند:
BUILTIN (نام حساب کاربری)
- BUILTIN\Administators
- BUILTIN\Guests
NT AUTHORITY (نماینده سیستم امنیتی داخلی است)
- NT AUTHORITY\SYSTEM
Security Identifiers (SID):
هر زمان که یک حساب کاربری جدید (یا گروه) ایجاد شود باید منحصر به فرد و از دیگر حساب های کاربری جدا باشد. اگر یک حساب کاربری با نام کاربر Joul ساخته شود، درحالی که قبلا یک حساب با همان userid موجود بوده باشد، ساخت حساب کاربری جدید با شکست مواجه می شود. اگر حساب کاربری به درستی ایجاد گردد، Win32 یک Security Identifier (SID) می سازد. SID یک ساختار داده است که یک حساب خاص را در یک دامنه خاص مشخص می کند.
هر SID منحصر به فرد است و Win32 هیچوقت دو SID مشابه تولید نمی کند. حتی اگر شما دو حساب با نام Joel در دو دامنه (domain) داشته باشید، قطعا domain1\Joel و domain2\Joel دارای SID های متفاوت می باشند.
هنگامیی که Win32 سیستم عامل می خواهد به یک حساب کاربری، حساب ماشین، حساب دامنه یا گروه (محلی و عمومی) مراجعه می کند به SID آن اشاره می کند. زمانی که ما به یک حساب یا گروه با اسم (مانند domain1\Joel) مراجعه می کنیم Win32 به دنبال SID مخصوص دامنه و حساب می گردد. برای آسان کردن کار برای ما (نه رایانه) Win32 یک SID را با یک رشته طولانی مانند زیر نمایش می دهد:
S-1-5-21-143984352-578909669-1869494990-1001
این رشته منحصر به فرد یک کاربر منحصر به فرد را در یک دامنه مشخص می کند.
typedef struct _SID { BYTE Revision; BYTE SubAuthorityCount; SID_IDENTIFIER_AUTHORITY IdentifierAuthority; #if ... DWORD *SubAuthority[]; #else DWORD SubAuthority[ANYSIZE_ARRAY]; #endif } SID, *PISID;
- Revision: نسخه SID ساختار موجود در یک SID مشخص را نشان می دهد.
- SubAuthorityCount: نشان دهنده تعداد مقادیر subauthority در یک SID است.
- IdentifierAuthority: بالاترین سطح امتیاز را که SID می تواند برای یک نوع مشخص از مدیر امنیتی مشخص کند شامل می شود.
- SubAuthority: اطلاعات مهمی را در SID نگه می دارد، که شامل یک یا تعداد بیشتری از مقادیر، از جنس subauthority می باشد. آخرین مقدار یک دامنه در یک (شبکه) enterprise را مشخص می کند. این داده domain identifier نامیده می شود(به غیر از داده آخر موجود در آرایه). آخرین مقدار در این سری (آرایه subauthority)، relative identifier (RID) نامیده می شود.
بعد از تبدیل یک SID از فرمت باینری به یک فرمت رشته، فهم آسان تری پیدا می کند:
S-R-X-Y1-Y2-Yn-1-Yn
- S: نشان دهنده این است که این رشته یک رشته SID است.
- R: نشان دهنده سطح revision است.
- X: نشان دهنده مقدار identifier authority است.
- Y: نشان دهنده یک سری از مقدار های subauthority می باشد (n مشخص کننده شماره هر مقدار است).
به طور خلاصه می توان گفت که SID همان چیزی است که WIN32 استفاده می کند تا یک حساب کاربری را در یک دامنه خاص مشخص کند.
Access Control Entries (ACE):
ما حالا میفهمیم که Win32 برای اشاره به یک حساب کاربری، از SID به عنوان یک راه آسان استفاده می کند. اما چگونه یک حساب کاربری (یک SID) با مجموعه ای از مجوز ها مرتبط می شود؟
Win32 به permission ها به عنوان یک کنترل دسترسی (Access Control) مراجعه می کند. اگر شما یک شئ داشته باشید (به عنوان مثال، یک فایل در یک هارد درایو)، باید در مدیریت دامنه یتان(Managers domain) آن مسئله که می تواند مشکل ساز باشد (به عنوان مثال joel) را کنترل کنید، به عنوان مثال می توان فایل را برای این عنصر مشکل ساز فقط قابل خواندن قرار دهید. شما می توانید این کار با ایجاد یک Access Control Entry انجام دهید(ACE).یک ACE یک راه آسان برای نگاشت یک اکانت (SID) به مجموعه ای از permission ها است. مجموعه ای از pemission های ACE با نام permission mask(یا به طور خلاصه mask) شناخته می شوند. Win32 در داخل خود این permission mask ها رو به صورت یک مقدار DWORD چهار بایتی ذخیره می کند. هر یک از permission ها با یک بیت مشخص هماهنگ می شود. این به این معنا است که زمانی که یک ACE ساخته می شود، permission های آن به گونه ای ساخته می شوند که می توانند با OR های منطقی permission های متفاوت ایجاد کنند.
$Permission = READ | WRITE | DELETE;
بنابر این شما اگر می خواهید به حساب کاربری(کاربران) به عنوان مثال Joel اجازه خواندن، نوشتن و پاک کردن یک فایل را بدهید، باید یک ACE بسازید که شامل SID مدیر(یا همانjoel ) و یک permission mask (READ | WRITE | DELETE) باشد.
شما می توانید ساختار کلی یک ACE را در زیر مشاهده کنید:
Access Control List (ACL):
هر مدیری که سرورهای پرونده را مدیریت می کند می تواند به شما بگوید که چه مجوزهایی روی یک پرونده قرار داده شده است. به عنوان مثال یک فایل می تواند شامل permission های زیر باشد:
هر یک از مجموعه account/permission های کاربر ها تمام اطلاعات لازم را برای ساخت یک ACE را دارند. بر فرض که شما می خواهید چندین ACE بسازید، یک نمونه از مجموعه اطلاعات لازم account/permission در عکس بالا توصیف شده است. برای اینکه ACE ها مفید باشند، آنها باید با یکدیگر گروه بندی شوند که بتوان آنها را برای برخی از اشیاء مانند فایل ها اعمال نمود.
گروهی از ACE ها با نام Access Control List (ACL) شناخته می شوند. سیستم عامل های Win32 از ACL برا گروه بندی منطقی ACE ها استفاده می کنند به طوری که آنها به راحتی می توانند بر روی یک شئ اعمال شوند. درست همانطور که یک دایرکتوری می تواند شامل گروهی از فایل ها باشد، یک ACL نیز می تواند شامل گروهی از ACE ها باشد. هر شئ Win32 که می تواند قابلیت secured را داشته باشد، از ACL برای تعیین کردن این که چه کسی به آن شئ دسترسی داشته باشد یا نداشته باشد استفاده می کند.
زمانی که شما مالک شئی می شوید، یک دسته از ACE هایی را که به حساب کاربر (SID) (که در مجموعه permission ها قرار داده اید (permission mask) ) نگاشت شده است را ساخته اید.
دو نوع ACL وجود دارد. نوع اول Discretionary Access Control List (DACL) می باشد، و نوع دوم System Access Control List (SACL) می باشد.
تفاوت بین دو نوع مختلف ACL:
DACL: این نوع ACL یک لیست از ACE ها است که مشخص می کند چه کسی حق دارد یا ندارد که به شئ دسترسی داشته باشد. برای مثال ممکن است یه یک اکانت اجازه خواندن، نوشتن یا پاک کردن را داشته باشد یا اجازه آن رد شده باشد.
این همان چیزی است که هنگام تغییر مجوز ها در Windows Explorer یا File Manager تنظیم می شود.SACL: این نوع از ACL شامل لیستی از ACE ها است که نشان می دهد Win32 آیا باید رویدادهای خاصی را در Log Event وارد کند یا خیر. یک رویداد ممکن است شامل موارد زیر باشد :
- خواندن شئ
- نوشتن شئ
- اجرای شئ
- پاک کردن یک شئ
- تغییر مجوز های (permission) شئ
- گرفتن مالکیت شئ (تغییر مالک)
اکثر کاربران بیشتر با DACL ها سر و کار دارند و کمتر با SACL درگیر می شوند، مگر اینکه شما سرپرستی باشید که دقیقاً باید تلاش کاربران برای دستیابی به اشیاء خاص را نظارت کند.بنابراین یک DACL نشان دهنده این است که کدام کاربران دسترسی خاصی دارند و SACL نشان دهنده این است که کدام رویداد وارد شده (logged) برای کدام کاربر است.
Object Owners and Groups:
گذشته از ACE های و ACL ها بیشتر اشیاء می توانند یک صاحب (owner) و گروه (group) داشته باشند. Object’s owner به طور ساده یک حساب کاربر است که object را ساخته است. انتصاب مجدد مالک به یک شئ امکان پذیر است اما فرض موجود این است که می توان کاربری را که شی را ساخته ردیابی کرد.
Object’s group به طور ساده یک global group است که نشان دهنده default group سازنده می باشد. Win32 از این استفاده نمی کند اما برای سازگاری با POSIX وجود دارد.
هر شئ که با یک مالک و گروه در ارتباط باشد از SID ها برای نشان دادن حساب و گروه استفاده می کنند.
به بیان دیگر: یک owner و group، SID های هستند که نشان دهنده یک user account و group کسی هستند که مسئول شئ می باشند.
Security Descriptors (SD):
در این مرحله باید بدیهی باشد که امنیت یک شئ مستلزم ایجاد یک دسته از ACE ها (نگاشت userid ها به permission mask ها) و گروه بندی آن ها در یک لیست است(چه DACL، ACL یا هر دو). SID ها user account را مشخص می کنند، و لازم است با global group جمع گردد. پس از بدست آوردن همه این چیز ها آنها را می توان به صورت مرتب در یک ساختار بزرگ به نام توصیف کننده امنیتی (Security Descriptor) قرار داد.پس از ایجاد یک SD، می توان آن را در یک securable object مورد استفاده قرار داد. یک SD را میتوان از فایل A استخراج نموده و به عنوان مثال برای فایل B مورد استفاده قرار داد. در این حالت تمام مقادیر DACL و SACL فایل A برای فایل B ذخیره می شود.
SD موجود را می توان با استخراج آن از securable object موجود دریافت کرد یا آن را از ابتدا ایجاد کرد. بنابر این شئ می تواند از یک شئ موجود(مانند یک فایل) بدست آمده یا اصلاح شده و سپس در یک securable object دیگر استفاده گردد. اصلاح، می تواند شامل هر چیزی مانند اضافه کردن ACE های جدید، تغییر permission mask در داخل یک ACE یا حذف ACE ها گردد.
پایان قسمت سوم
- 1
-
Windows Access Control List (ACL)
قسمت دوم (مفاهیم)
مباحث مورد بررسی در این مقاله:
- Access Rights for Access-Token Objects
- Security Descriptors
- Securable Objects
Access Rights for Access-Token Objects:
برنامه نمی تواند لیست کنترل دسترسی یک شئ را تغییر دهد مگر اینکه برنامه حق انجام آن کار را داشته باشد. این حقوق توسط یک security descriptor در access token شئ کنترل می شود. برای گرفتن یا تنظیم کردن security descriptor برای یک access token، می توانید تابع GetKernelObjectSecurity() و تابع SetKernelObjectSecurity() را فراخوانی کنید. زمانی که تابع OpenProcessToken() یا OpenThreadToken() را برای گرفتن یک هندل access token فراخوانی می کنید، سیستم دسترسی درخواستی را در برابر DACL در security descriptor توکن بررسی می کند. موارد زیر حقوق دسترسی معتبر برای اشیاء دارای access token می باشند:
- DELETE، RED_CONTROL، WRITE_DAC و WRITE_OWNER دسترسی استاندارد می باشند. Access token از SYNCHRONIZE به عنوان دسترسی استاندارد پشتیبانی نمی کنند.
- ACCESS_SYSTEM_SECURITY برای دریافت یا تنظیم SACL در security descriptor شئ.
در قسمت زیر دسترسی خاص برای access token ها ذکر شده اند:
- TOKEN_ADJUST_DEFAULT: مورد نیاز برای تغییر owner، primary group یا DACL یک access token.
- TOKEN_ADJUST_GROUPS: مورد نیاز برای تنظیم ویژگی های (attributes) یک گروه در یک access token.
- TOKEN_ADJUST_PRIVILEGES: مورد نیاز برای فعال یا غیر فعال کردن یک privileges در یک access token.
- TOKEN_ADJUST_SESSIONID: مورد نیاز برای تنظیم session ID یک access token. امتیاز(privilege) SE_TCB_NAME مورد نیاز می باشد.
- TOKEN_ASSIGN_PRIMARY: مورد نیاز برای متصل شدن به یک primary token یک فرایند. برای انجام این کار امتیاز SE_ASSIGNPRIMARYTOKEN_NAME مورد نیاز است.
- TOKEN_DUPLICATE: مورد نیاز برای کپی کردن یک access token.
- TOKEN_EXECUTE: STANDARD_RIGHTS_EXECUTE و TOKEN_IMPERSONATE را ترکیب می کند.
- TOKEN_IMPERSONATE: مورد نیاز برای متصل شدن به یک impersonation access token یک فرایند.
- TOKEN_QUERY: مورد نیاز برای پرس و جو درباره یک access token.
- TOKEN_QUERY_SOURCE: مورد نیاز برای پرسو جو در باره منبع (source) یک access token.
- TOKEN_READ: ترکیبی از STANDARD_RIGHTS_READ و TOKEN_QUERY می باشد.
- TOKEN_WRITE: ترکیبی از STANDARD_RIGHTS_WRITE، TOKEN_ADJUST_PRIVILEGES، TOKEN_ADJUST_GROUPS و TOKEN_ADJUST_DEFAULT می باشد.
- TOKEN_ALL_ACCESS: ترکیبی از تمام دسترسی های ممکن مرتبط با token.
Security Descriptors:
یک security descriptor از اطلاعات امنیتی تشکیل شده است که با یک securable object مرتبط است. یک security descriptor از یک ساختار SECURITY_DESCRIPTOR که با security information مرتبط است تشکیل شده. یک security descriptor می تواند شامل security information زیر باشد:
- SID های owner و primary group یک شئ.
- یک DACL که حقوق دسترسی، که تعیین کننده مجاز بودن یا رد شدن دسترسی یک کاربر یا گروه خاصی را مشخص می کند.
- یک SACL که انواع تلاش های دسترسی که سوابق حسابرسی را برای شئ ایجاد شده مشخص می کند.
- مجموعه ای از بیت های کنترلی که به معنای یک security descriptor یا اعضای جداگانه آن است.
ویندوز تابع هایی (API) را برای تنظیم یا بازیابی کردن security information موجود در security descriptor اشیاء ارائه کرده است. بعلاوه، تابع هایی نیز برای ساخت و مقدار دهی (اولیه) کردن یک security descriptor برای یک شئ وجود دارد. برنامه هایی که با security descriptor ها در اشیاء Active Directory کار می کنند می توانند از توابع امنیتی ویندوز یا رابط های امنیتی ارائه شده توسط Active Directory Service Interfaces (ADSI) استفاده کنند.
Securable Objects:
یک Securable Objects یک شئ است که می تواند یک security descriptor داشته باشد. هر نوع از Securable Object مجموعه ای از دسترسی های خاص و دسترسی های عمومی را تعریف می کند. در قسمت پایین می توانید تابع هایی را مشاهده کنید که برای دستکاری اطلاعات امنیتی برخی از Securable Objects مشترک نشان می دهد.
- Files or directories on an NTFS file system: GetNamedSecurityInfo()، SetNamedSecurityInfo()، GetSecurityInfo()، SetSecurityInfo()
- Named pipes, Anonymous pipes: GetSecurityInfo()، SetSecurityInfo()
- Processes, Threads: GetSecurityInfo()، SetSecurityInfo()
- File-mapping objects: GetNamedSecurityInfo()، SetNamedSecurityInfo()، GetSecurityInfo()، SetSecurityInfo()
- Access tokens: SetKernelObjectSecurity()، GetKernelObjectSecurity()
- Window-management objects (window stations and desktops): GetSecurityInfo()، SetSecurityInfo()
- Registry keys: GetNamedSecurityInfo()، SetNamedSecurityInfo()، GetSecurityInfo()، SetSecurityInfo()
- Windows services: GetNamedSecurityInfo()، SetNamedSecurityInfo()، GetSecurityInfo()، SetSecurityInfo()
- Local or remote printers: GetNamedSecurityInfo()، SetNamedSecurityInfo()، GetSecurityInfo()، SetSecurityInfo()
- Network shares: GetNamedSecurityInfo()، SetNamedSecurityInfo()، GetSecurityInfo()، SetSecurityInfo()
- Interprocess synchronization objects (events, mutexes, semaphores, and waitable timers): GetNamedSecurityInfo()، SetNamedSecurityInfo()، GetSecurityInfo()، SetSecurityInfo()
- Job objects: GetNamedSecurityInfo()، SetNamedSecurityInfo()، GetSecurityInfo()، SetSecurityInfo()
- Directory service objects: این اشیاء توسط Active Directory Objects اداره شده.
تصویر زیر یک مثال از رابطه بین securable object (a folder) و security descriptor را نمایش می دهد.
پایان قسمت دوم
- 2
-
Windows Access Control List (ACL)
قسمت اول (مفاهیم)
مباحث مورد بررسی در این مقاله:
- Access Control
- Access Control Model
- Access Control Components
مقدمه:
در این مقاله ما تلاش میکنیم که چگونگی اجرای امنیت در سیستم عامل های ویندوز را یادبگیریم. Access Control یکی از مهمترین و اساسی ترین مباحث در Windows SDK Platform از دسته امنیتی می باشد. ما با Access Control که در ویندوز استفاده میشود شروع می کنیم و سپس در هر بخش ، به جزئیات بیشتری می پردازیم. در این مسیر ما توابع موجود برای دستکاری و تعامل با شیئ های متنوع ویندوز در بحث امنیت را نیز بررسی می کنیم. برنامه کاربردی در بخش های بعدی ارائه خواهد شد. برنامه نمونه، برنامه سطح پایین به زبان C ، بدون هیچ رابط کاربری گرافیکی (GUI) برای یادگیری بهتر می باشد.
Access Control:
در سند های ماکروسافت (MSDN) ذکر شده است که در آغاز، سیستم عامل های ویندوز از استاندارد منسوخ کلاس C2 پیروی می کردند. Access Control به این موضوع اشاره میکند که چه کسی به چه منابعی از سیستم عامل میتواند دسترسی داشته باشد. برنامه ها توابع کنترل سطح دسترسی را فراخوانی می کنند تا تنظیم کنند که چه کسی میتواند به منابع خاصی دسترسی داشته باشد، یا اینکه دسترسی به منابع فراهم شده توسط برنامه ها را کنترل کند.Access Control Model:
Access Control Model شما را قادر می سازد توانایی یک فرایند را برای دسترسی به securable object ها یا انجام کارهای مختلف مدیریت سیستم، کنترل کنید. یک فرایند، یک security context است که یک برنامه در آن اجرا می شود. معمولا security context با کاربر مرتبط است، بنابر این تمام برنامه ها تحت token فرایند، با permissions و privilegesصاحب کاربر اجرا می شوند.Access Control Components:
دو مولفه اساسی در مدل کنترل دسترسی وجود دارد:- Access tokens: که شامل اطلاعاتی در مورد کاربر داخل شده می باشد.
- Security descriptors: که حاوی اطلاعات امنیتی است که از یک securable object محافظت می کند.
زمانی که یک کاربر وارد سیستم می شود، سیستم نام و رمز عبور کاربر را تایید می کند. اگر ورود به سیستم موفقیت آمیز بود، سیستم یک access token تولید می کند. هر فرایندی که به نمایندگی از این کاربر اجرا می شود یک نسخه از این access token را خواهد داشت. access token از شناسه های امنیتی (SID) تشکیل شده که حساب کاربری (user account) و هر حساب گروهی (group accounts) را که کاربر به آن تعلق دارد را شناسایی می کند.
این شناسه حاوی لیستی از privileges است که توسط کاربر یا گروه کاربرها نگهداری می شوند. سیستم زمانی که یه فرایند سعی می کند تا به یک securable object دسترسی پیدا کند یا درخواست گرفتن امتیاز administration را می دهد، از این نشانه برای شناسایی کاربر استفاده میکند.
وقتی یک securable object ایجاد می شود، سیستم به آن security descriptor اختصاصی می دهد که حاوی اطلاعات امنیتی است که توسط سازنده آن مشخص شده است، یا اگر توسط سازنده مشخص نشده باشد اطلاعات امنیتی پیش فرض را به آن اختصاص می دهد.
برنامه ها می توانند از توابع برای بازیابی و تنظیم اطلاعات امنیتی برای یک شئ موجود استفاده کنند. security descriptor مالک شئ را مشخص می کند و میتواند شامل access control lists (ACLs) زیر باشد:- Discretionary access control list (DACL): کاربرها و گروه هایی را که اجازه دسترسی به شئ را دارند یا ندارند مشخص می کنند.
- System access control list (SACL): که نحوه کنترل حسابرسی سیستم را برای دسترسی به شئ کنترل می کند.
یک ACL از لیستی از access control entries (ACEs) تشکیل شده. هر ACE یک مجموعه حقوق دسترسی را مشخص می کند که شامل یک SID می شود که یک سرپرست برای کسی که حق اجازه دادن، رد کردن یا حسابرسی را می دهد، مشخص میکند. یک حساب کاربری (user account)، گروه کاربری (group account)، جلسه ورود (logon session) میتواند یک سرپرست باشد. یک جلسه ورود زمانی آغاز می شود که کاربر وارد کامپیتر شود. تمام فرایندها در یک logon session دارای primary access token شبیه به یکدیگر می باشند. access token شامل اطلاعات درباره security context جلسه ورود ، شامل SID کاربر، شناسه ورود به سیستم و logon SID می باشد. تصویر زیر نشان می دهد که وقتی یک کاربر وارد سیستم می شود چه اتفاقی می افتد. به خاطر داشته باشید که کاربر نکته مهمی نیست، بلکه نام کاربری و رمزعبور وی در سیستم ایجاد شده است. کاربر تنها به عنوان یک شئ در ویندوز اعتبار دارد.
یک access token یک شئ است که security context یک فرایند یا ریسمان را توصیف می کند. اطلاعات داخل token شامل هویت و امتیازات یک حساب کاربر مرتبط با فرایند یا ریسمان می باشد. زمانی که یک کاربر وارد سیستم می شود، سیستم رمز ورود کاربر را با اطلاعات ذخیره شده در پایگاه داده امنیتی خود مقایسه کرده، و آن را تایید یا رد میکند. اگر رمز ورود تایید گردد، سیستم یکaccess token تولید میکند. هر فرایندی از طرف این کاربر اجرا گردد یک کپی از این access token را دارد.
سیستم از این access token برای شناسایی کاربر، زمانی که یک ریسمان با یک شئ قابل اطمینان در تعامل است یا تلاش می کند که یک کار سیستمی را انجام دهد که به امتیاز (خاصی) نیاز دارد استفاده میکند.
access token ها از اطلاعات زیر تشکیل شدند:- SID صاحب حساب.
- SID های گروه هایی که کاربر عضو آن هستند.
- SID ورود به سیستم نشان دهنده logon session اخیر می باشد.
- لیستی از privilege هایی که توسط کاربر یا گروه های کاربر در اختیار دارد.
- صاحب SID.
- SID برای primary group.
- DACL پیشفرض، که سیستم از آن استفاده می کند، زمانی استفاده می شود که کاربر یک securable object، بدون مشخص کردن یک security descriptor می سازد.
- منبع access token.
- اینکه آیا token یک token اصلی است یا جعل هویت است (primary or impersonation).
- لیست اختیاری محدود کننده SID ها(optional list of restricting SIDs).
- سطح جعل هویت جاری.
- سایر آمار.
هر primary token یک access token است که معمولا فقط به وسیله هسته ویندوز ساخته می شود. ممکن است آن به یک فرآیند اختصاص داده شود تا اطلاعات امنیتی پیش فرض برای آن فرآیند را نشان دهد.
impersonation token یک access token است که برای گرفتن اطلاعات امنیتی یک فرآیند کلاینت ایجاد شده است و به سرور اجازه می دهد تا فرایند کلاینت را در عملیات امنیتی جعل هویت کند.
هر فرایند یک primary token دارد که security context حساب کاربر که با فرایند مرتبط است را توصیف میکند. به صورت پیشفرض، سیستم از primary token زمانی استفاده می کند که یک ریسمان یک فرایند با یک securable object در تعامل باشد. علاوه بر این، یک ریسمان می تواند یک حساب کاربر را جعل هویت کند. جعل هویت به ریسمان اجازه می دهد با استفاده از security context با securable object ها در تعامل باشد. ریسمانی که کلاینت را جعل هویت می کند هر دو خاصیت primary token و impersonation token را دارد. شما می توانید با فراخوانی تابع OpenProcessToken() هندل primary token فرایند را بازیابی کنید.- AdjustTokenGroups(): اطلاعات گروه را در access token تغییر می دهد.
- AdjustTokenPrivileges(): یک (یا چند) privilege را در access token فعال یا غیر فعال می کند.
- CheckTokenMembership(): مشخص میکند که یک SID مشخص شده در یک access token فعال است یا خیر.
- CreateRestrictedToken(): یک access token جدید می سازد که یک نسخه محدود شده از access token موجود می باشد. restricted token های شده می توانند SID های غیر فعال، privilege های پاک شده، و یک لیست از SID های محدود شده داشته باشند.
- DuplicateToken(): یک access token جدید از روی access token موجود می سازد.
- DuplicateTokenEx(): یک primary token یا impersonation token می سازد که یک نسخه از یک access token موجود را کپی می کند.
- GetTokenInformation(): اطلاعات یک access token را بازیابی می کند.
- IsTokenRestricted(): مشخص میکند که آیا یک token یک لیست از SID های محدود کننده دارد یا نه.
- OpenProcessToken(): هندل یک primary access token که مربوط به به یک فرایند است را بازیابی می کند.
- OpenThreadToken(): هندل یک impersonation access token که مربوط به به یک نخ است را بازیابی می کند.
- SetThreadToken():به یک نخ یک impersonation token را حذف یا اختصاص می دهد .
- SetTokenInformation(): صاحب token، primary group یا DACL پیشفرض را تغییر می دهد.
تابع های access token از ساختار های زیر برای توصیف کامپوننت های access token استفاده می کنند.- TOKEN_CONTROL: اطلاعاتی که یک access token را مشخص می کند.
- TOKEN_DEFAULT_DACL: عضو DACL پیش فرض سیستم که از آن در security descriptors اشیائ جدیدی که توسط نخ ها ساخته می شود استفاده می کند.
- TOKEN_GROUPS: یک (یا چند) SID و ویژگی های group SID ها در access token را مشخص می کند.
- TOKEN_OWNER: مالک پیش فرض SID برای توصیف کننده اشیائ جدید.
- TOKEN_PRIMARY_GROUP: یک primary group SID پیش فرض برای توصیف کننده امنیت شئ جدید.
- TOKEN_PRIVILEGES: یک privilege مرتبط با یک access token. همچنین مشخص می کند که آیا privilege ها فعال شده اند یا خیر.
- TOKEN_SOURCE: منبع access token.
- TOKEN_STATISTICS: آمار مرتبط با یک access token.
- TOKEN_USER: SID کاربر مرتبط با access token.
تابع های access token از enumeration type های زیر استفاده می کنند.- TOKEN_INFORMATION_CLASS: نوع اطلاعاتی که قرار است ازaccess token گرفته شود یا تنظیم شود را مشخص می کند.
- TOKEN_TYPE: نوع access tokenرا مشخص میکند که قرار است از نوع primary یا impersonation باشد.
تصاویر دیگر از ساختار token:مثال:
Privilege: حق سیستم برای انجام کارهای مختلف مربوط به سیستم مانند خاموش کردن سیستم، بارگیری دیوایس درایور یا تغییر زمان سیستم. access token کاربر، شامل یک لیست از privilege ها که به وسیله کاربر یا گروه کاربر ها نگه داری می شود.securable object: یک شئ است که می تواند یک security descriptor داشته باشد. هر چیزی در ویندوز که Windows objects نام گرفته باشد securable است. برخی اشیاء بی نام، مانند اشیاء process و thread، هم نیز می توانند security descriptors داشته باشند. برای اکثر securable object میتوانید یک security descriptor در هنگام فراخوانی تابع سازنده شئ مشخص کنید. برای مثال می توانید security descriptor را در توابع CreatFile و CreatProcess مشخص کنید. به علاوه، تابع های امنیتی ویندوز شما را قادر می سازند تا اطلاعات امنیتی securable objects سیستم عامل های دیگر را گرفته یا تنظیم کنید.
security context: ویژگی های امنیتی یا قانون هایی که در حال حاضر قابل اجرا هستند. برای مثال، کاربر فعلی که وارد سیستم شده است یا شماره شناسایی شخصی که با یک کارت هوشمند وارد شده.
security descriptor: ساختار و داده های همراه که شامل اطلاعات امنیتی برای یکsecurable object است. security descriptor صاحب شئ و primary group را مشخص می کند. همچنین میتواند حاوی یک DACL (که دسترسی به یک شئ را کنترل می کند)، و یک SACL (برای کنترل دستیابی به شئ) است.
پایان قسمت اول
- 3
-
در این قسمت قصد داریم تا با چند مفهوم پایهای تر در سیستم عامل ویندوز آشنا شویم. در ابتدا مفهوم (VAS (Virtual address spaces را مورد بررسی قرار میدهیم.
فضای آدرسهای مجازی (VAS)یک مُدل برای مدیریت بهتر حافظه میباشد، زمانی که یک پردازنده اقدام به خواندن یا نوشنتن در یک مکان حافظه میکند، از یک آدرس مجازی استفاده میکند. به عنوان بخشی از عملیات خواندن یا نوشتن، پردازنده آدرس مجازی را به آدرس فیزیکی ترجمه میکند. دسترسی به حافظه از طریق یک آدرس مجازی مزایای زیر را دارد :
- یک برنامه میتواند از محدودهٔ مجاور آدرس های مجازی برای دسترسی به یک بافر حافظه بزرگ استفاده کند که در حافظه فیزیکی به یکدیگر متصل نیستند.
- یک برنامه میتواند طیفی از آدرس های مجازی برای دسترسی به بافری بزرگتر از حافظه فیزیکی موجود را مورد استفاده قرار دهد.
- حافظهٔ فیزیکی ( که به اندازه 4 کیلوبایت میباشد) را به فایل دیسک میفرستد. صفحات داده یا کد بین حافظهٔ فیزیکی و دیسک در صورت مورد نیاز منتقل میگردد (اولویت با صفحات قدیمی تر میباشد.که دیرتر به آنها مراجعه شده است).
- آدرس های مجازی مورد استفاده در فرایندهای مختلف از یکدیگر جدا شده اند. کد در یک فرآیند نمیتواند حافظهٔ فیزیکی را که توسط فرآیند دیگری یا سیستم عامل مورد استفاده قرار میگیرد تغییر دهد.
محدودهٔ آدرسهای مجازی که در فرآیند در دسترس است، فضای آدرس مجازی برای فرایند میباشد. هر فرایند حالت کاربر، دارای فضای آدرس مجازی خصوصی خود است. برای یک فرایند 32 بیتی، فضای آدرس مجازی معمولاً محدودهٔ 2 گیگابایتی از
0x00000000
تا0x7FFFFFFF
است. برای یک فرآیند 64 بیتی فضای آدرس مجازی محدوده 8 ترابایتی0x00000000000
تا0x7FFFFFFFFFF
است.- طیفی از آدرسهای مجازی گاهی اوقات طیفی از حافظههای مجازی نامیده میشوند.
این نمودار برخی از ویژگی های آدرس مجازی را نشان میدهد:
این نمودار فضاهای آدرس مجازی را برای دو فرایند 64 بیتی نشان میدهد: Notepad.exe و MyApp.exe هر فرایند دارای فضای آدرس مجازی خود است که از
0x000'0000000
تا0x7FF'FFFFFFFF
قرار دارد. هر بلوک آبی نشان دهنده یک صفحه (به اندازه 4 کیلوبایت) از حافظه مجازی یا فیزیکی است. توجه داشته باشید که فرایند Notepad از سه صفحه پیوندی از آدرس های مجازی استفاده میکند، با شروع از آدرس0x7F7'93950000
. اما این سه صفحه مجاور آدرسهای مجازی به صفحات غیر مستقیم در حافظه فیزیکی نقش میشود. همچنین توجه کنید که هر دو فرایند با استفاده از یک صفحه از حافظه مجازی شروع از0x7F7'93950000
استفاده میکنند، اما آن صفحات مجازی به صفحات مختلف حافظه فیزیکی نقش میشوند.فضای کاربر و فضای سیستم:
فرایندهایی مانند Notepad.exe و MyApp.exe در حالت کاربر اجرا میشوند. اجزاء اصلی سیستمعامل و بسیاری از درایورها بیشتر در حالت کِرنل مورد استفاده قرار میگیرند. هر فرایندِ حالت کاربر دارای فضای آدرس خود است ، اما تمام کدهایی که در حالت هسته اجرا میگردند، یک فضای آدرس مجزا به نام فضای سیستم دارند (دارای فضای آدرس مشترک هستند) . فضای آدرس مجازی برای فرآیند کاربر حالت فعلی کاربر،
user space
نامیده میشود.در ویندوز 32 بیت، فضای آدرس مجازی موجود در دسترس 2 به توان 32 بایت (4 گیگابایت) است. معمولاً 2 گیگابایت کمتر برای فضای کاربر میباشد و ۲ گیگابایت بالاتر برای فضای سیستر در نظر گرفته میشود.
در ویندوز 32 بیتی شما میتوانید گزینه ای (در هنگام بوت شدن) را مشخص کنید که بیش از 2 گیگابایت برای فضای کاربر در دسترس باشد . در نتیجه آدر مجازی کمتری در دسترس سیستم قرار میگیرد. شما میتوانید حجم فضای کاربر را تا 3 گیگا بایت افزایش دهید ، در این صورت فقط 1 گیگ فضا برای سیستم باقش میماند.
در ویندوز های 64 بیتی مقدار فضای آدرس مجازی 2 به توان 64 بایت (16 اگزابایت) میباشد . اما تنها بخش کوچکی از این محدوده استفاده میگردد محدوده 8 ترابایت از
0x000'00000000
تا0x7FF'FFFFFFFF
برای فضای کاربر استفاده میشود و بخش هایی از 248 ترابایت از0xFFFF0800'00000000
تا0xFFFFFFFF'FFFFFFFF
برای فضای سیستم استفاده میگردد.کُدِ در حال اجرا در حالت کاربر دسترسی به فضای کاربر دارد، اما دسترسی به فضایِ سیستم ندارد. این محدودیت باعث میشود که کد کاربر حالت خواندن یا تغییر ساختار داده های محافظت شده سیستم عامل را نداشته باشد. کد در حالِ اجرا در حالت هسته دارای دسترسی به فضای کاربر و فضای سیستم میباشد.
درایورها (راهاندازهایی) که در حالت هسته اجرا میشوند باید در نوشتن یا خواندن در فضای آدرس کاربر به دلایل زیر بسیار محتاط باشد:
- یک برنامه یوزر مُد (حالت کاربر)، یک در خواست برای خواندن برخی از دادهها را به یک دستگاه میفرستد. این برنامه آدرس اولیه یک بافر برای دریافت داده ها را فراهم میکند.
- یک دستگاه روتینِ درایور در حالت اجرا در حالت هسته، عملیات خواندن را شروع میکند و کنترل را به تماس گیرنده خود بازمیگرداند سپس اینتراپت دستگاه هر نخ (ترد) را که در حال اجرا است را قطع میکند.
- در این مرحله، درایور نباید دادهها را به آدرس اولیها ارسال کند که در برنامه کاربر، در قسمت اول به آن اشاره شد. این آدرس در فضای آدرس مجازی فرایند است که درخواست را آغاز کرده است، که به احتمال زیاد همانند فرایند فعلی نیست.
مخازن (استخر حافظه) صفحهبندی شده و صفحهبندی نشده (Paged pool and Nonpaged pool)
- در فضای کاربری، تمام صفحات حافظه فیزیکی را میتوان به عنوان یک فایل دیسک به صورت صحیح برگرداند. در فضای سیستم، برخی صفحات فیزیکی میتوانند از بیین بروند و برخی نیز نمیتوانند.
- فضای سیستم دارای دو منطقه برای تخصیص حافظه پویا میباشد : paged pool و nonpaged pool.
- در حالت paged pool حافظه میتواند به صورت فایل (در صورت نیاز) به دیسک منتقل گردد.
- در حالت nonpaged pool هرگز حافظه نمیتواند به دیسک منتقل گردد.
کتابخانهٔ پیوند پویا و فایلهای اجرایی (DLL و PE)
در این قسمت کمی با ساختار فایل های اجرایی و بخصوص DLL ها آشنا میشویم. در خلاصه ترین حالت میتوان گفت Dynamic link library نام کتابخانههایی است که توسط برنامه ها استفاده میشوند و توسط مایکروسافت پیاده سازی شده ( که اغلب دارای پسوند dll میباشند).
این فایل ها همانند ساختار فایل های exe در ویندوز دارای ساختار (PE (Portable Executable میباشد. این کتابخانهها میتوانند شامل کد و داده و منابع (ریسورسها) باشند.
یکی از مزایای فایل های dll این است که یک بار در حافظه بارگذاری میشود و میتواند توسط چندین برنامه مورد استفاده قرار گیرد (به صورت مجازی برای هر برنامه کپی میشود). میتوان dll ها را در موقه نیاز در برنامه بارگذاری کرد و هر جا که دیگر مورد نیاز نبود آن را خالی (Unload) کرد.
از طرفی دیگر میتوان از آن برای استفاده از برنامه های قابل بهروزرسانی نیز استفاده کرد به این صورت که میتوان آیکنها ، فونتها و کدهایی که در هسته اصلی برنامه جایگاهی ندارند را درون dll ها قرار داد و در هنگام بهروزرسانی تنها این dll ها را تعویض کرد.
هر فایل اجرایی جدا از کدها و دادههای خود میتواند اطلاعات را از خارج از خود و از dll بگیرد. در هر فایل pe بخشی از هدر فایل، شامل آدرس جدول آدرس وارد کردن (Import) میشود که اطلاعات موجود در آن، آدرس توابعی که از dll ها فراخوانی میشود را در خود نگه داری میکنند ( البته این آدرس ها با پایهٔ آدرس dll ترکیب میشوند که در تصویر دوم هم قابل مشاهده است). تصویر زیر خلاصهای ار هدر فایلهایی با ساختار PE میباشد. در این عکس
import adress table
حاوی آدرسiat
در برنامه میباشد.
شکل زیر یک توضیح کلی تر و بهتر در اختیار ما میگذارد. در این شکل میتوان iat را بین دو بخش کد و داده ببینید.
نمونه ای از فراخوانی یکی از توابع dll ها را در زیر میتوان مشاهده کرد. این تصویر کد اسمبلی یک برنامه میباشد.
مثال های کاربردی:
مثال اول:
در مثال اول یک dll ساخته و آن را با rundll32.exe اجرا کنید. از قسمت پروژه جدید (New project) در قسمت سیپلاسپلاس پروژه ای از نوع win32project بسازید. در صفحه باز شده Next را بزنید. dll را انتخاب کرده و سپس تیک Empty project را بزنید و پروژه را بسازید. سپس به پروژه خود یک فایل cpp اضافه کنید و کدهای زیر را در آن بنویسید:
//[dll01.dll] #include <windows.h> extern "C" __declspec (dllexport) void __cdecl hello() { ::MessageBox(0, L"hello world", 0, 0); } BOOL APIENTRY Dll(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { return TRUE; }
برنامه را کامپایل کنید، سپس cmd را باز کرده و دستور زیر را در آن تایپ کنید .
(در آدرسی که dll قرار دارد دستور را اجرا کنید یا این که آدرس کامل dll را به آن بدهید)
c:\rundll32.exe dll01.dll,hello
شکل کلی استفاده از این دستور:
RUNDLL32.EXE <dllname>,<entrypoint> <optional arguments>
با اجرای این دستور پنجرهای را میبینید که در آن پیغام موجود در dll را چاپ میکند.
مثال دوم:در این مثال، دیالال (dll) ای که در مثال قبل ساختید را در یک برنامه دیگر با زبان
c++
ایجاد و بعد از اتمام کار، آن را آن بارگذاری کنید.کُد برنامه مورد نظر به صورت زیر خواهد بود:
#include <windows.h> #include <stdio.h> typedef void(__cdecl *MYPROC)(); int main(void) { HINSTANCE hinstLib; MYPROC ProcAdd; BOOL fFreeResult, fRunTimeLinkSuccess = FALSE; // Get a handle to the DLL module. hinstLib = LoadLibrary(TEXT("c://dll01.dll")); // If the handle is valid, try to get the function address. if (hinstLib != NULL) { ProcAdd = (MYPROC)GetProcAddress(hinstLib, "hello"); // If the function address is valid, call the function. if (NULL != ProcAdd) { printf("dll is loaded\n"); fRunTimeLinkSuccess = TRUE; (ProcAdd)(); } // Free the DLL module. fFreeResult = FreeLibrary(hinstLib); if (fFreeResult && ProcAdd) { printf("dll is Unloaded\n"); } else if (!fFreeResult && ProcAdd) { printf("error , dll is not Unload\n"); } } // If unable to call the DLL function, use an alternative. if (!fRunTimeLinkSuccess) { printf("Message printed from executable\n"); } system("pause"); return 0; }
- 2
- 1
-
در این قسمت قصد داریم تا کمی با مفهوم Process و Thread آشنا شویم .
Process :
در آغاز برنامه ها بصورت فایلهایی بر روی هارد درایو قرار دارند . برای اجرا شدن آنها ، این فایلها از هارد به حافظه اصلی (یعنی رم) منتقل میشوند و کتابخانه های مورد نیاز درون آن لود میشوند و ..... سپس برنامه اجرا میگردد .
در یک تعریف کلی از Process میتوان گفت یک برنامه اجرا شده در سیستم عامل میباشد که خود از واحدی کوچکتر به نام Thread (در ادامه توضیح داده میشود) تشکیل شده که کوچکترین واحد پردازشی در ویندوز میباشد که برای محاسبه به داخل CPU فرستاده میشود .در شکل زیر میتوانید حالت کلی یک Process را مشاهده کنید .
از ویژگی یک Process میتوان به دارا بودن آدرس مجازی منحصر به فرد خود اشاره کرد و همچنین وجود PID منحصر به فرد که با فعال شدن هر Process این مقدار عددی به آن نسبت داده میشود تا برای رجوع کردن به Process از این عدد منحصر به فرد بجای نام آن استفاده شود.
نکته دیگر در مورد این است که اگر یک Process در درون خود Process دیگری را بسازد ، در آنها رابطه پدر و فرزندی بوجود می آید و در نتیجه آن به وجود آمدن دو Thread و در نتیجه امکان استفاده از حالت پردازش همزمانی میشود . که البته API های ویندوز این امکان را به ما میدهند که حالت انتظار والد را هم انتخاب کنیم تا حالت پردازش همزمانی بوجود نیاید .دستورات کاربردی : (CMD)
1- مشاهده پروسس های در حال اجرا با دستور زیرtasklist
2-بستن یک Process
taskkill
به عنوان مثال :
taskkill /f /pid 9876
Thread :
همانطور که در بالا تشریح کردیم هر Process از حداقل یک Thread تشکیل شده تا از آن به عنوان واحد اجرایی برای خود استفاده کند . در واقع Process بدون Thread از دید سیستم عامل دلیلی برای ادامه کار ندارد و پروسس را از بین میبرد .
یکی از کاربرد های Thread ایجاد پردازش همزمان در Process ها هست ، هر چند میتوان با ایجاد چند Process نیز به پردازش همزمان رسید اما برای ارتباط و گرفتن خروجی از هر Thread و استفاده در Thread دیگر به مشکل خورده (هرچند با روش هایی میتوان میان آنها حافظه به اشتراک گذاشت) .از Thread میتوان برای بهینه تر کردن برنامه استفاده کرد ، Thread در ویندوز کوچک ترین واحد پردازش میباشد که توسط برنامه نویس درون یک برنامه تعریف شده و سپس با فراخوانی API مناسب Thread ساخته و در صف Thread ها برای ورود به پردازنده قرار میگیرند .
هر Thread شامل یک stack و یک TLS(Thread Local Storage) میباشد.(در شکل قسمت Process قابل مشاهده میباشد) .
هر Thread که برای اجرا وارد پردازنده میگردد Task نامیده میشود . ویندوز ، سیستم عاملی چند برنامه ای (Multiprogramming) و چند وظیفه ای (Multitasking) را پشتیبانی میکند . در ویندوز برای پیاده سازی چند وظیفه ای از مدل (Multithreading) استفاده میشود .
شکل زیر نشان دهنده Thread و رابطه آن را با CPU در حالت کلی نمایش میدهد.
- 1
- 4
Thread Environment Block (TEB) Process Environment Block (PEB)
در سیستم عامل ویندوز
ارسال شده در
ما قصد داریم نگاهی به ساختار Thread Environment Block (TEB) با استفاده از WinDbg بیندازیم. از آنجا که ساختار TEB در حالت کاربر در دسترس است و توسط اجزای ویندوز در حالت کاربر مانند NTDLL و KERNEL32 استفاده می شود ، برای پرس و جو در مورد ساختار نیازی به اشکال زدایی هسته نداریم.
winDbg x64 را باز مینماییم.
اکنون notepad.exe را باز می کنیم. پس از باز شدن ، می توانیم با رفتن به مسیر File -> Attach to a Process -> notepad.exe به notepad.exe در WinDbg متصل شویم. از طرف دیگر ، می توانید از کلید های پیش فرض که باید F6 باشد استفاده کنید.
با WinDbg به آن متصل میشویم.
پس از انجام این کار ، پنجره فرمان WinDbg نمایش داده می شود. پنجره فرمان فضای کاری است که ما باید دستورات را به تشخیص خود وارد کنیم تا نتایج مختلف دلخواه را به دست آوریم. به عنوان مثال ، اگر بخواهیم چیزی را دستکاری کنیم ، یا اطلاعاتی را در مورد چیزی جستجو کنیم ، می توانیم این کار را با یک دستور انجام دهیم. WinDbg دارای طیف وسیعی از دستورات موجود است و می توانید در اینجا بیشتر بدانید: http://windbg.info/doc/1-common-cmds.html
ما از دستور dt استفاده می کنیم. "dt" مخفف "Display Type" است و می تواند برای نمایش اطلاعات مربوط به یک نوع داده خاص ، از جمله ساختارها استفاده شود. در مورد ما ، این بیش از حد مناسب است زیرا از ساختارها پشتیبانی می کند و ما باید اطلاعاتی در مورد ساختار TEB پیدا کنیم.
ما می توانیم از دستورالعمل زیر برای پرسیدن اطلاعات در مورد ساختار TEB استفاده کنیم.
اگر به بالای ساختار نگاه کنیم ، بلوک Process Environment Block را پیدا می کنیم.
+0x060 ProcessEnvironmentBlock : Ptr64 _PEB
ما می توانیم ببینیم که WinDbg نوع داده این فیلد را با عنوان "Ptr64 _PEB" برچسب گذاری می کند. این بدان معناست که نوع داده اشاره گر به ساختار PEB (PPEB) است. از آنجا که ما در حال اشکال زدایی یک برنامه کامپایل شده 64 بیتی هستیم (notepad.exe از آنجا که سیستم عامل ما 64 بیتی است) ، آدرس ها به جای 4 بایت مانند محیط 32 بیتی 8 بایت هستند ، به همین دلیل "64" به "Ptr"
ما می توانیم فیلدهای ساختار PEB را با دستور WinDbg زیر مشاهده کنیم.
همانطور که می بینیم ، فیلد های زیادی برای ساختار PEB وجود دارد. هرچند ما در بخشهای عملی فقط بر تعدادی از آنها تمرکز خواهیم کرد.
قبل از اینکه بتوانیم ادامه دهیم ، باید به طور مختصر در مورد چگونگی یافتن بلوک محیط فرآیند صحبت کنیم. این آدرس در FS: [0x30] در Thread Environment Block/Thread Information Block برای فرایندهای 32 بیتی قرار دارد و در GS: [0x60] برای پردازش های 64 بیتی قرار دارد.
برای شروع ، قسمت سوم ساختار PEB ("BeingDebugged ") را می توان بخوانید تا مشخص شود آیا فرآیند فعلی از طریق اشکال زدایی متصل شده است یا خیر...
یک روال معمول از API Win32 به نام IsDebuggerPresent (KERNEL32) وجود دارد و این API با بررسی قسمت BeingDebugged در ساختار PEB کار می کند. ما می توانیم با مهندسی معکوس kernel32.dll خودمان این را تأیید کنیم.
همانطور که می بینیم ، kernel32.dll یک روال معمول به نام IsDebuggerPresentStub دارد که IsDebuggerPresent را صدا می زند. این به این دلیل است که محیطی که من این تصاویر را از آن دریافت می کنم ویندوز 10 64 بیتی است و مایکروسافت به استفاده از KernelBase.dll (معرفی شده با شروع ویندوز روی آورد. با این حال ، برای سازگاری با قبل، kernel32.dll همچنان مورد استفاده اسناد خود قرار می گیرد-و اگر آنها پشتیبانی خود را از دست داده بودند ، مجبور بودند بیشتر از آنچه قبلاً به پروژه ماژول جدید منتقل شده اند ، و باید وجود داشته باشد در آن زمان بسیاری از نرم افزارهای ناسازگار برای ویندوز 8+ بود.
بنابراین ، ما باید نگاهی به KernelBase.dll بیندازیم.
KernelBase.dll یک API صادر شده به نام IsDebuggerPresent دارد.
پایان قسمت دوم