دسته Archives: اسمبلی

آنالیز ساختار ویندوز و روت کیت های سطح هسته-بخش پایانی

اگر کمی با برنامه نویسی کرنل آشنایی داشته باشید، حتما ساختار DRIVER_OBJECT را به خوبی می شناسید. این ساختار دارای فیلدی به نام MajorFunction است که آرایه ای از نوع PDRIVER_DISPATCH که آدرس روتین های مدیریت IRP دریافتی را در خود نگهداری می کند. IRP ها در wdm.h تعریف گردیده اند، نمیخواهیم وارد مبحث برنامه نویسی سطح کرنل شویم پس بیشتر وارد جزییات نمی شویم. اگر بتوانیم به ساختار DRIVER_OBJECT یک درایور دسترسی پیدا کنیم می توانیم عمل هوک را برای IRP های دریافتی آن انجام دهیم و IRP های آن درایور را مشاهده نماییم. ساده ترین راه برای دسترسی به این ساختار استفاده از تابع IoGetDeviceObjectPointer() است. این تابع آدرس Device Object را به عنوان خروجی بر میگرداند و درواقع Driver Object فیلدی از Device Object است.ساختار Device_Object ها را در تصویر زیر میبینیم:

Device_Object

همانگونه که مشاهده می کنیم فیلد NextDevice به دیوایس بعدی اشاره می کند وقتی درایورها به هم متصل شده اند و یک chain تشکیل دهند می توان مقادیر آن را مشاهده نماییم.  هر DeviceObject دارای DriverObject خودش می باشد که در فیلد DriverObject مشخص گردیده است. برای مشاهده درایورها می توانیم از کامند !object \device\ استفاده نماییم که لیستی از کل آبجکت ها را نشان می دهد. سپس برای نمایش استک از کامند  !devstackمی توانیم استفاده نماییم.

اطلاعات بیشتر

آنالیز ساختار ویندوز و روت کیت های سطح هسته-بخش سوم

در ادامه بحث های مطرح شده در آنالیز ساختار ویندوز و روت کیت های سطح هسته-بخش اول  و همچنین آنالیز ساختار ویندوز و روت کیت های سطح هسته-بخش دوم ادامه بحث را دنبال خواهیم کرد.

یکی دیگر از تکنیک های که روت کیت ها استفاده می نمایند درواقع می توان گفت نسل جدیدتر روت کیت ها، استفاده از تکنیک DKOM[1] نام دارد. در این تکنیک ساختار های کرنل را تغییر میدهیم . ساختارهایی مانند لیست پروسه های فعال ، درایورها.

در این روش هیچگونه هوک و یا تغییری در جداولی مانند SSDT,IDT انجام نمیدهیم. روت کیت ها می توانند با Unlink نمودن یک شی EPROCESS از ActiveProcesLinks خود را پنهان نمایند و پروسه ای را از دید تابع ZwQuerySystemInformation() که برای بدست آوردن لیست پروسه های اجراشده در سیستم استفاده می نماییم پنهان نماید. کرنل از ساختاری به نام KPCR[2] استفاده می کند. در این ساختار اطلاعات مهم و اساسی مانند IDT ، GDT و … ذخیره می شود. برای دسترسی راحتتر به KPCR کرنل آدرس آن را در نسخه های x86 ویندوز درون رجیستر fs و همچنین در ویندوزهای x64 در رجیستر gs ذخیره می کند. KPCR شامل ساختاری است به نام KPRCB[3] است. KPCR مستند شده است ولی KPRCB یک ساختار خصوصی است و تنها در ntoskrnl مورد استفاده قرار می گیرد. این ساختار شامل اطلاعات درباره Scheduling پروسه ها می باشد.

Kernel processor control region

در ساختار _KPRCB فیلدی به نا م CurrentThread وجود دارد که برایمان مهم می باشد همانطور در تصویر زیر می بینیم این فیلد از نوع ساختار _KTHREAD است:

kernel processor control block

برای مشاهده محتوای ساختارهای KPCR و KPRCB می توانیم از دستور های !pcr و !prcb استفاده نماییم، مقدار Current  را به یاد داشته باشید.

pcr-command-windbgاطلاعات بیشتر

آنالیز ساختار ویندوز و روت کیت های سطح هسته-بخش دوم

در ادامه بحث های مطرح شده در آنالیز ساختار ویندوز و روت کیت های سطح هسته-بخش اول  ادامه بحث را دنبال خواهیم کرد.

سطح هسته همانند سطح کاربر دارای هوک های خاص خودش است که معروفترین آن ایجاد تغییرات دلخواه در جداولی است که آدرس توابع مورد نیاز سیستم را در خود نگهداری می کنند:

  • System Service Dispatch Table (SSDT)
  • Interrupt Descriptor Table (IDT)

آدرس توابع سطح کرنل درون جدول SSDT نگهداری می شود(توابع nt*). هنگامیکه روند اجرا یک برنامه سطح کاربر میخواهد به سمت کرنل هدایت شود  ID مرتبط با تابع کرنل درون رجیستر EAX قرار می گیرد و رجیستر EDX به لیست پارامترهای که بایستی به تابع ارجاع داده می شود اشاره می کند، سپس با اجرای دستور int 2e و یا sysenter روند اجرا پروسه به سطح کرنل خواهد رفت.  هنگامیکه وقفه ای رخ می دهد سیستم عامل با جستجو در IDT ، روتین مرتبط با مدیریت آن وقفه را بدست میاورد. این جدول تمامی وقفه ها را درون خود نگهداری می کند. روتین هندل کننده وقفه 0x2e  تابع KiSystemService() از ntoskrnl است. برای بازگشت به سطح کاربر از دستور iret استفاده می شود. در صورتی که از دستور sysenter استفاده شود برای بازگشت به سطح کاربر از دستور sysexit استفاده خواهد شد. برای پشتیبانی از دستور sysenter ویندوز در زمان بوت آدرس روتین مرتبط را بجای IDT در رجیستر  MSR[1]  ذخیره می کند. . اسکریپت زیر را می توانید از این آدرس[2] دریافت نمایید. با دستور زیر در windbg میبینیم که handler این وقفه تابع  KiSystemService() است :

اطلاعات بیشتر

آنالیز ساختار ویندوز و روت کیت های سطح هسته-بخش اول

در این پست و چند پست آتی به نحوه آنالیز و تحلیل Rootkit ها خواهیم پرداخت که پیش نیاز آن، آشنایی با ساختار و تکنیک های مورد استفاده در آنها می باشد. Rootkit ها مختص به یک سیستم عامل و پلتفرم خاص نیستند، در واقع یک اصطلاح می باشد که به دسته خاصی از بدافزارها اشاره می شود. روت کیت هایی برای MS Windows ، Linux ، Cisco IOS و … نوشته شده و می توان نوشت. مایکروسافت درباره روت کیت چنین می گوید که نویسندگان بدافزارها برای پنهان کردن بدافزار از روت کیت ها استفاده می کنند، حال روت کیت بدافزار است یا بخشی از بدافزار و تعریف و تعابیر دیگر از این واژه ، خود را درگیر این قبیل مباحث نخواهیم کرد.

rootkit

Rootkit را می توان به دو بخش root و kit تقسیم کرد تا بهتر به مفهوم آن آشنا شد. سیستم عامل ویندوز به طورکلی به دو سطح تقسیم می شود یعنی Ring0 و Ring3 (به هر سطح Ring گوییم). Ring0 دارای بالاترین سطح دسترسی می باشد که به آن Kernel-mode نیز گفته می شود و همچنین Ring3 دارای کمترین سطح دسترسی که به آن نیز User-mode گوییم.

هر سطح دارای ساختار و ویژگی خاص خود می باشد بنابراین در مبحث دیباگینگ نیز تفاوت هایی وجود دارد. WinDBG دیباگر مایکروسافتی است که می توان در هر دوسطح عمل دیباگ را انجام دهیم ولی نکته قابل توجه کارایی آن است که در Ring3 دیباگر هایی مانند OllyDBG ، ImmunityDBG و… کارایی بهتری را دارا هستند. با توجه به ویژگی های WinDBG ، در دیباگ سطح هسته از آن استفاده می کنیم. راه های دیباگ در windbg را می توان در تصویر زیر مشاهده نمود:

windbg-debug-ways

 

برای دیباگ کرنل به دو صورت Remote و یا Local می توانیم عمل نماییم. Local Debug در سطح هسته بدین معنی است که خود سیستم مان را دیباگ نماییم که در این حالت دارای محدودیت هایی خواهیم بود و کارهایی مانند: توقف در اجرا، قرار دادن نقاط توقف در روند اجرا و امثالهم را نمی توان انجام داد. برای این حالت علاوه بر WinDBG ممکن است به ابزار LiveKD [1]  نیاز شود. در حالت Remote که در واقع بحث اصلی مان خواهد بود، علاوه بر روش های مختلف موجود که محبوبترین آن Serial است با استفاده از ابزار Virtual KD [2]  نیز میتوانید دیباگ را انجام دهید. روش Serial دارای سرعت پایین تری نسبت به Virtual KD می باشد. در حالت Serial سرعتی که داریم   bps  115200 است ولی در Virtual KD  حداکثر سرعت در Virtual Box نیز 450 KB/s  و برای VMware حداکثر 150 KB/s  است. بعد از نصب و راه اندازی Virtual KD در ماشین مجازی براحتی میتوان با استفاده از WinDBG و یا IDA به آن متصل شد و دیباگینگ را انجام دهیم.

اطلاعات بیشتر

چگونه یک متغیر مقداردهی نشده، باگ ایجاد می کند؟

سلامی دوباره، بعد از مدتها استراحت و بی حوصلگی در راستای تجزیه نشدن و همچنین جزیی از طبیعت قرار نگرفتن یه پستی توی بلاگ میزارم تا این پست رو همانند پکت های Keep-Alive در نظر بگیرید.  :دایی

خوب، قرار نیست نحوه اکسپلویت کردن و تکنیک هارو توضیح بدیم فقط میخواهیم کمی درباره خطرات مقداردهی نکردن متغیرها در برنامه و نحوه بوجود آمدن باگ صحبت کنیم، واس خیلی ها از جمله خودم پیش اومده که در زبان C/C++ متغیری مانند Integer رو مقداردهی اولیه انجام ندادیم ، یادمون رفته و یا برحسب عادت در زبان های برنامه نویسی دیگر مثل VB6.0 اینکار رو انجام ندادیم. بنظرم تنها دلیلی که بعضی ها هنوزم که هنوزه طرفدار VB6.0 هستند! همین مقداردهی اولیه نکردن متغیرهاست، اگر شما حتی نوع متغیر رو تعریف نکنین بطور خودکار متغیر از نوع Variant در نظر گرفته میشه و هر DATA Type بخواهید میتونید درون متغیر بریزید!!! اینها انسانهای خاص هستند و خاص هم که فحش نیست !؟

خوب از بحث اصلیمون دور نشیم،اگر استاد همون درس برنامه نویسی و یا افراد دیگری که ازشون این سوال “متغییر مقدار دهی نشده ولی دارای مقدار هست و خروجی به ما نشون میده” رو پرسیدین بهمون گفتن که وقتی یک نوع Integer رو مقدار دهی نمیکنیم ، مقداری  Random درون متغیر ریخته میشه؟!؟ و اینم جز خیلی از حرفاس که وارد مغزمون کردن تا بیشتر ندونیم و نپرسیم. (انگاری دلم خیلی پره :دایی) بایک مثال خیلی ساده و راحت میخواهیم به صحت و سقم این دلیل پی ببریم. خوب سورس زیر رو کامپایل و اجرا میکنیم:

بعد از اجرا مقدار این متغیر رو داریم میبینیم که بایستی این یک مقدار تصادفی باشه و در هر بار اجرا مقداری مختلف ببینید، من درون سیستم خودم فقط این مقدار رو میبینیم و نتیجه میگیرم که مقدار Random نیست:

Ouput

حال برنامه را درون یار همیشه همراهمون باز میکنیم تا دلیل این امر رو کشف کنیم.

debuggingاطلاعات بیشتر

آموزش shell code نویسی در لینوکس – Linux قسمت اول

به نام دانای بر حق

مقدمه

پیرو آموزش هایی که SadeghPM عزیز در مورد شل کد نویسی قرارداده بودش ما سعی کردیم این آموزش رو برای لینوکس ادامه بدیم البته با کسب اجازه از ایشان، و اما اگر بخواهیم در یک جمله در مورد شل کد صحبت کنیم شل کد کدهای ماشینی هستند که برای انجام یه سری عمل به سیستم عامل تحویل داده میشند و نتیجه خاصی دارند و این اعمال میتونه خرابکارانه باشه یا نباشه و حالا برای کسب اطلاعات بیشتر به آموزش SadeghPM قسمت اول مراجعه کنید در اینجا، حال آنکه شل کد های میتونند با زبان ماشین یا همون همون آپکد های hex یا هگزادسیمال بهتره بگیم باشند یا می تونند به صورت فرامینی باشند که در که در بخش های که از سیستم عامل اجرا شوند که گاهی پذیرای command line هستند به صورت متنی ارسال شده و اجرا شوند که بحث ما اکنون حول محور این بخش command line هستش.

تفاوت ارسال command line در ویندوز و لینوکس

خب در این شکی نیست در مبحث شل کد نویسی در لینوکس بسیار دست انسان باز هستش تا ویندوز، که در ادامه توضیح مبسوط تر میدیم، تفاوت اولی که میتونیم ازش یاد بکنیم این هستش کد های شما باید در ویندوز در cmd و یا همون command port می باشد ولی در لینوکس از bash و برنامه ی terminal استفاده میشود حال چرا لینوکس قدرت بیشتری داره، علت اول این هستش که این سیستم عامل جوری تعریف شده که حدودا ۹۵٪ از اعمال در این سیستم عامل غیر وابسته به واسط گرافیکی هستش و با terminal میشود به سرعت انجام کار داد، به طور مثال تقریبا در تمام ابر توزیع های لینوکس یه نسخه سرور دارد که فاقد GUI یا واسط گرافیکی میباشد و همواره باید از پروتوکل SSH و خط فرمان اجرای دستور کرد.

اجرای کد در terminal

برای اجرای دستور در ترمینال ما به سادگی میتونیم  با کلید ترکیبی Ctrl+Alt+T اون رو اجرا کنه، و کد های مورد نظر مون رو بنویسیم، به عنوان مثال با نوشت دستور dir لیست فایل ها و فولدر های جاری به شما نمایش داده میشود و و به همین تریتب شما موفق میشوید حال آنکه ما برای shellcode نویسی نیاز به کامپایلر و یا اسمبلر ها داریم که تو لینوکس به صورت پیش فرض کامپایلر c به به نام gcc نصب هستش و خیالتون رو از این بابت راحت می کنه و حالا برای اجرا کد های اسمبل با نصب nasm که به سادگی میتونین کد ها اسمبلی رو هم اجرا کنید بیاییم مراحل زیر رو با هم اجرا کنیم، ولی قول بدین زیاد روی نکنین سیستم منفجر کنین 😀 :

دستور ها در ترمینال اجرا میشود تا اولین برنامه یعنی hello world رو در اسمبلی بنویسیم.اطلاعات بیشتر