پاسخ سوالات قسمت قبل
- اسکریپتهای گیدرا به این علت کاربردی هستند که میتوانند وظایف مهندسی معکوس را بهصورت اتوماتیک انجام دهند. بعضی از این وظایف عبارتاند از: جستجو برای رشتهها و الگوهای تکراری کد، رفع ابهام خودکار کد و افزودن کامنت ها و توضیحات برای بهبود دیس اسمبلی
- اسکریپتها بر اساس کارکرد آنها مرتب شدهاند. در ظاهر اسکریپتها با توجه به محل آنها روی سیستم شما مرتب شدهاند اما در حقیقت در ابتدای هر اسکریپت در بخش @category برچسب مربوط به کارکرد هر اسکریپت تعیین میشود.
در قسمتهای قبل، منابع و ابزارهای مهم، آشنایی اولیه و نکات مهم دررابطهبا این آموزشها معرفی شد. اگر اولینبار است که این مقاله را میبینید، برای استفاده هر چه بیشتر و بهتر ازقسمت صفر شروع کنید! قسمت قبل را نیز از اینجامیتوانید مشاهده کنید.
فصل 2- اتوماسیون مهندسی معکوس با گیدرا (ادامه)
بریم که اولین اسکریپتهای خودمون رو بنویسیم و ببینیم که چطوری میشه یک اسکریپت رو از صفر نوشت.
کلاس اسکریپت
برای توسعهی یک اسکریپت جدید در گیدرا ابتدا روی Create New Script در منوی Script Manager کلیک کنید. بعد از آن باید مشخص کنید که از چه زبانی استفاده خواهید کرد:
ابتدا ساختار اسکریپتها به زبان جاوا را بررسی میکنیم:
اگر از جاوا برای توسعهی اسکریپتهای خود استفاده کنید، اسکریپت شما 3 بخش اصلی خواهد داشت. اولین بخش اسکریپت کامنت ها هستند:
//TODO write a description for this script //@author //@category Strings //@keybinding //@menupath //@toolbar
اینکه چه چیزی را باید در ادامهی کامنت ها بنویسید واضح است و فقط @menupath را توضیح میدهیم. این کامنت به شما این امکان را میدهد تا بتوانید اسکریپتهای خود را در منوی گیدرا قرار دهید:
دستهبندی اسکریپت در @category انجام شده است اما با استفاده از @menupath میتوان به شکل دیگری اسکریپت را انتخاب کرد. مثلاً اگر بنویسیم:
//@menupath Tools.Packt.Learn Ghidra Scripts
دقت کنید که مسیر با کاراکتر. مشخص میشود؛ میتوانید از منوی گیدرا اسکریپت را انتخاب کنید:
بخش بعدی یک اسکپریت جاوا import ها هستند. ترجیحاً به این بخش دست نزنید و اولین ماژول اضافه شده به برنامه به هیچ وجه نباید دستکاری شود. تمام اسکریپتهای گیدرا باید GhidraScript و متد run() را به ارث ببرند:
import ghidra.app.script.GhidraScript; import ghidra.program.model.util.*; import ghidra.program.model.reloc.*; import ghidra.program.model.data.*; import ghidra.program.model.block.*; import ghidra.program.model.symbol.*; import ghidra.program.model.scalar.*; import ghidra.program.model.mem.*; import ghidra.program.model.listing.*; import ghidra.program.model.lang.*; import ghidra.program.model.pcode.*; import ghidra.program.model.address.*;
تمام ابزاری که به برنامه import شدهاند دارای داکیومنتیشن کامل و مناسبی هستند که در JAVADOC گیدرا قرار دارد و برای توسعهی اسکریپت باید به آن رجوع کنید.
داکیومنتیشن API های گیدرا برای JAVADOC
با کلیک بر روی منوی Help و انتخاب Ghida API Help برای بار اول، داکیومنتیشن API های گیدرا بصورت خودکار ایجاد می شود. پس از آن میتوانید برای ابزاری که به برنامه import شده داکیومنتیشن ها را بخوانید.
در آخر بخش بدنه ی اسکریپت وجود دارد که از GhidraScript متد run() را وارد برنامه ی خود می کنید. در ادامه ی این آموزش با بخش های مختلف ابزار import شده بیشتر کار خواهیم کرد:
public class NewScript extends GhidraScript { public void run() throws Exception { //TODO Add User Code Here } }
اگر میخواهید اسکریپتهای خود را به زبان پایتون بنویسید هم API دقیقاً مشابه زبان جاواست اما اسکریپت دو بخشی است و شامل یک header که همان کامنت ها هستند و بدنه اسکریپت که کد شما را در خود جای میدهد، میشود:
#TODO write a description for this script #@author #@category Strings #@keybinding #@menupath #@toolbar #TODO Add User Code Here
در اینجا به این علت هیچ چیزی را به برنامه import نمیکنیم که پایتون مستقیماً از API جاوا بهره میبرد و این اتفاق به علت اجرا شدن برنامهی پایتون در بستر Jython تنظیم شدهی گیدرا رخ میدهد.
از آنجایی که داکیومنتیشن مذکور ممکن است برای توسعه دهندگان پایتون ناخوانا یا دشوار باشد میتوانید از منوی Window و گزینهی Python مفسر پایتون را فعال کنید و از گزینهی کامل کردن خودکار بهره ببرید (با کلید TAB) و یا به روش مرسوم دیگری داکیومنیشن را ببینید.
اگر با زبان پایتون آشنا باشید میدانید که استفاده از تابع help() در مفسر میتوانید توضیحات و داکیومنتیشن دستورات مختلف را بخوانید. به همین علت استفاده از حداقل 2 مانیتور و باز نگهداشتن مفسر پایتون برای نوشتن اسکریپتهای پایتون در گیدرا بسیار توصیه میشود.
بسیار خوب! تا اینجا هر چیزی که برای شروع توسعهی اسکریپت نیاز داشتیم را باهم مرور کردیم و یاد گرفتیم که چطور میشود به داکیومنتیشن های آنها و API های جاوا دسترسی داشت. حالا زمان تمرین است. اسکریپتی که در ادامه مینویسیم و بررسی میکنیم برای مقابله با برخی از ویروسهای کامپیوتری که بهصورت مرسوم قابل پاک شدن از سیستم شما نیستند مورداستفاده قرار میگیرد.
توسعه ی اسکریپت
برنامهای که در این قسمت توسعه میدهیم تمام بایتهای برنامه را به دستور بدون عملیات (NOP) برای پردازنده تبدیل میکند. ابتدا برنامه را به زبان جاوا مینویسیم. توجه کنید که به بخش وسط برنامه دست نمیزنیم و تنها بخش کامنت ها و بدنه برای ما مهم است. میتوانید برنامه را از اینجا دریافت کنید.
در قسمت @keybinding تنظیم میکنیم که برنامه با فشردن کلیدهای Ctrl +Alt+ Shift + N اجرا شود.
//This simple script allows you to patch bytes with NOP opcode //@author Packt //@category Memory //@keybinding ctrl alt shift n //@menupath Tools.Packt.nop //@toolbar
در ادامه به import ها دست نمیزنیم و بدنهی تابع را مینویسیم:
public class NopScript extends GhidraScript { /** empty line */ public void run() throws Exception { Address startAddr = currentLocation.getByteAddress(); byte nop = (byte)0x90; try { int istructionSize = getInstructionAt(startAddr).getDefaultFallThroughOffset(); removeInstructionAt(startAddr); for(int i=0; i<istructionSize; i++){ setByte(startAddr.addWrap(i), nop); } disassemble(startAddr); } catch (MemoryAccessException e) { popup("Unable to nop this byte"); return; } } }
ابتدا باید آدرس اشارهگر فعلی گیدرا را استخراج کنیم (خط 03) در این آدرس دستوری تعریف نشده است (خط 06 تا 08)، بایتها را با opcode مورد نظرمان (دستور NOP) که مقدار 144 دارد (0x90) جایگزین میکنیم خط 09 تا 11) و دوباره بایتها را دیس اسمبل میکنیم خط 12). داکیومنت های دستورات استفاده شده را بررسی کنید تا عملیات انجام شده را بهتر بفهمید. کد پایتون برنامهی بالا هم به شکل زیر است:
#This simple script allows you to patch bytes with NOP opcode #@author Packt #@category Memory #@keybinding ctrl alt shift n #@menupath Tools.Packt.Nop #@toolbar currentAddr = currentLocation.getByteAddress() nop = 0x90 instructionSize = getInstructionAt(currentAddr).getDefaultFallThroughOffset() removeInstructionAt(currentAddr) for i in range(instructionSize): setByte(currentAddr.addWrap(i), nop) disassemble(currentAddr)
خلاصه
بالاخره یاد گرفتیم که چطور یک اسکریپت بسیار ساده را به زبان جاوا یا پایتون بنویسیم. در آینده از تمام آموختههای خود برای نوشتن اسکریپتهای تحلیل بدافزار و تحلیل باینری استفاده میکنیم و اسکریپتهای پیچیدهتر و بسیار جلب تری مینویسیم. در قسمت بعدی در مورد debug در گیدرا با استفاده از Eclipe IDE صحبت میکنیم و میبینید که چطور میتوان ویژگیهای گیدرا را از این هم بیشتر توسعه داد و دسترسیهای داخلی گیدرا را نیز بررسی میکنیم.
سؤال ها
- چرا تفاوتی بین API های اسکریپت نویسی پایتون و جاوا وجود ندارد؟
منبع:سیسوگ