پاسخ سؤالات قسمت قبل
- نوار ابزاری که در بخش بالا-سمت راست صفحهی دیس اسمبلی قرار دارد به شما اجازه میدهد که نمایش دیس اسمبلی را سفارشیسازی کنید: با کلیک راست روی گزینهی PCode، میتوانید PCode را در لیست دیس اسمبلی ببینید. برای هر دستور اسمبلی حداقل یک PCode تولید میشود.
- نمایش دیس اسمبلی، نمایش دستورات برنامه است که به زبان پردازنده نوشته شدهاند. نمایش دیکامپایلر اما کد دیکامپایل شده به زبان C را نمایش میدهد.
در قسمتهای قبل، منابع و ابزارهای مهم، آشنایی اولیه و نکات مهم دررابطهبا این آموزشها معرفی شد. اگر اولینبار است که این مقاله را میبینید، برای استفاده هر چه بیشتر و بهتر از قسمت صفر شروع کنید! قسمت قبل را نیز از اینجا میتوانید مشاهده کنید.
فصل 2- اتوماسیون مهندسی معکوس با گیدرا
در این فصل در مورد اتوماسیون مهندسی معکوس با گیدرا و نوشتن اسکریپتهای گیدرا صحبت میکنیم. ابتدا باهم بررسی میکنیم که چه ویژگیهای خوب، خلاقانه و بسیار متمرکزی به عنوان اسکریپتها در گیدرا قرار گرفته است. چند صد اسکریپت پیش فرض گیدرا معمولاً برای بیشتر نیازهای اتوماسیون مهندسی معکوس کافی هستند.
پس از اینکه با این اسکریپتها آشنا شدیم، بررسی میکنیم که چطور عمل میکنند. سپس کلاس اسکریپتهای گیدرا را بررسی میکنیم تا درک بهتری نسبت به پارامترهای داخلی آنها پیدا کنید و در بخش آخر این فصل از این آموختهها استفاده میکنیم.
در انتها شما یاد میگیرید که چطور اسکریپتهای گیدرای خود را توسعه دهید. برای این کار نیاز به آشنایی کلی با API های گیدرا دارید و خوشبختانه میتوانید به دو زبان جاوا و پایتون برنامهی خود را بنویسید چرا که API های گیدرا برای دو زبان مشابه هم هستند.
بهصورت خلاصه در این فصل موارد زیر بررسی میشوند:
- اسکریپت های داخلی گیدرا
- تحلیل کلاس اسکریپت گیدرا و API گیدرا
- نوشتن اسکریپت خودتان
منابع تکنیکال
برای چند قسمت آینده از کدهای کتاب Ghidra Software Reverse Engineering for Beginners استفاده میکنیم که ریپازیتوری های گیتهاب آن اینجا قرار دارند.
ویدیوی مربوط به این فصل نیز از اینجا قابل مشاهده هستند.
استفاده و بهکارگیری اسکریپتهای موجود
اسکریپتهای گیدرا به شما این امکان را میدهند تا وظایف مهندسی معکوس خود را زمانی که با تحلیل باینری سر و کار دارید به اتوماسیون بسپارید. بیایید بررسی کنیم که چطور میتوان از این اسکریپتها در CodeBrowser برای برنامهی hello world استفاده کرد. نقطهی شروع ما برنامهی hello world است که در محیط گیدرا بارگذاری کردهایم، همانطور که در فصل اول در مورد ویژگیهای گیدرا توضیح دادیم و برنامه را بارگذاری کردیم.
در فصل اول (02) به این مسئله اشاره کردیم که استفاده از گیدرا شامل استفاده از اسکریپتهای مختلفی نیز میشود. برای دسترسی به این اسکریپتها وارد بخش Window شوید و روی Script Manager کلیک کنید. همچنین میتوانید روی گزینهای که در نوار دسترسی سریع گیدرا در تصویر زیر برای شما مشخص شده است کلیک کنید.
همانطور که در بخش folder browser در سمت چپ مشاهده میکنید، تمام اسکریپتهای از پیش نصبشده در پوشههای مشخص و متفاوتی دستهبندی شدهاند که با کلیک روی هرکدام، اسکریپتهای موجود در آن پوشه نمایش داده میشوند:
در تصویر بالا یک بخش با مربع قرمز مشخص شده است. اگر روی آن کلیک کنید میتوانید مسیر پوشههای اسکریپت را در سیستم خود ببینید و به آن اضافه و از آنها کم کنید: (ولی فعلاً به چیزی دست نزنید)
اینجا نقطهی شروع کار ما با اسکریپتهاست. شما میتوانید تمام اسکریپتهای موجود در گیدرا رو تحلیل کنید و در محیط خود گیدرا آنها را تغییر بدید و متناسب با نیاز خود آنها را اصلاح کنید. تحلیل اسکریپتها به شما کمک میکند که بفهمید اسکریپتها چطوری کار میکنند و چطور میتوانید متناسب با نیاز خود آنها را بهینه کنید. با کلیک بر روی گزینههای edit script میتوانید اسکریپتهای موجود در محیط گیدرا را تغییر دهید و با کلیک بر روی creat a new script، اسکریپت جدید خود را ایجاد کنید:
برنامهی hello world جملهی hello world را در خروجی نمایش میدهد. این خروجی یک string است. ما میتوانیم از اسکریپتهای مرتبط با string در گیدرا استفاده کنیم و ببینیم که چطور استفاده از اسکریپتها تحلیل ما را سرعت میبخشد. همانطور که در تصویر زیر میبینید اسکریپتهای پایتون و جاوا هردو در یک پوشه قرار دارند:
برای مثال بیایید اسکریپت RecursiveStringFinder.py را بررسی کنیم. این اسکریپت میتواند سرعت آنالیز شما را افزایش دهد و تمام توابع و string ها مرتبط با آنها را مشخص کند. این اتفاق میتواند به شما کمک کند تا وظیفهی یک تابع را بدون خواندن حتی یک خط کد بفهمید.
بیایید اسکریپت را اجرا کنیم. تابع _mainCRTStartup() را در برنامه hello world به عنوان ورودی (با استفاده از قرار دادن موس روی تابع) به اسکریپت میدیم و خروجی را در script console مشاهده میکنیم.
در تصویر پایین میبینید که RecursiveStringFinder.py لیست توابع برنامه را به همراه رفرنس string های آنها باز گردانده است. برای مثال تابع _mainCRTStartup() اولین تابعی است که اجرا میشود(با توجه به نشانه گذاری و اینکه کاملاً سمت چپ قرار دارد مشابه کد پایتون) و پس از آن تابع __pei386_runtime_relocator() که توسط کامپایلر برای ساخت برنامه ایجاد شده است اجرا میشود و دارای یک string با محتوای ” Unknown pseudo relocation bit size%d. \n” است. نشانگر ds به ما میفهماند که متنی که جلوی آن قرار گرفته یک رشته (string) است. همانطور که میبینید بالاخره بعد از چند تابع و رشته که توسط کامپایلر به برنامه معرفی شده بودند بالاخره به تابع main() میرسیم که دارای رشتهی “Hello world.” ماست:
اسکریپت قبلی به زبان پایتون توسعه یافته بود و از تابع getStringRefrences() (خط 04) استفاده میکرد تا operand های دستورات را دریافت کند ( خط 07) که به چیزی اشاره دارند (خط 10). وقتی که چیزهایی در دادهها مشخص شدهاند و رشته هستند (خط 12 تا 14) به لیست خروجی برنامه اضافه میشوند و نهایتاً آنها را در console میبینیم. بیاید برنامه را بهتر کنیم. این برنامه اصلاح شده تا تنها اسکریپتهایی که برای ما جذاب هستند در خروجی نمایش داده میشوند. تابع isAnInterestingString() (خط 15) تصمیم میگیرد که آیا باید رشته را به لیست نهایی اضافه کرد یا نه (خطهای 16 تا 20).
فرض کنید دنبال URL ها در یک برنامه میگردید، مثلاً در یک بدافزار سرور هکرها اینگونه مشخص میشود یا در محصولات اینترنت اشیا پروتکلهای ارتباطی و سروری که سنسورها و عملگرهای مختلف با آن در ارتباط هستند مشخص میشود. برای این کار اسکریپتی که پیشتر از آن استفاده کردیم را باز میکنیم و تابع isAnInterestingString() (خطوط 0 تا 2) را به آن اضافه میکنیم. ضمناً قبل از نوشتن هر اسکریپتی ابتدا جست و جو کنید که از قبل وجود نداشته باشد.
def isAnInterestingString(string): """Returns True if the string is interesting for us""" return string.startswith("http") def getStringReferences(insn): """Get strings referenced in any/all operands of an instruction, if present""" numOperands = insn.getNumOperands() found=[] for i in range(numOperands): opRefs = insn.getNumOperandReferenc(i) for o in opRefs: if o.getReferenceType() .is Data(): string = getStringAtAddr(o.getToAddress()) if string is not None and \ isAnInterestingString(string): found.append(StringNode( insn.getMinAddress(), o.getToAddress(), (string) return found
اسکریپت بالا بهسادگی میتواند بهبود یابد تا URL های دقیقتری را در کد پیدا کند و این در زمان مهندسی معکوس بدافزارها بسیار مهم است. حتی میتوانید فقط با تغییر محتوای تابع اول برنامه آن را متناسب با نیاز خود تغییر دهید.
تابع TranslateStringsScript.java را به اختصار بررسی میکنیم تا چیزی از قلم نیفتد. این تابع پیشوند و پسوند TODO به شکل یک رشته را به رشتههای دیگر برنامه اضافه میکند. این مسئله زمانی کاربرد دارد که نیاز است رشتههای رمز گذاری شده را علامت گذاری کنید تا بعداً آنها را رمزگشایی کنید.
خلاصه
در این قسمت یاد گرفتیم که چگونه از اسکریپت های گیدرا استفاده کنیم و آنها را متناسب با نیاز خود تغییر دهیم. در قسمت بعدی اسکریپت های ساده ی خودمان را مینویسیم و API های داخلی گیدرا برای جاوا را تحلیل میکنیم.
سوال ها
- چرا اسکریپت های گیدرا کاربردی هستند؟ چه کارهایی میتوان با آنها انجام داد؟
- اسکریپت ها در گیدرا چگونه مرتب شده اند؟ آیا این مرتب سازی به محتوای سورس کد وابسته است یا به محل اسکریپت روی سیستم شما؟
منبع:سیسوگ