تزریق کد به یک
برنامه در حال اجرا ( یا Process Injection )
در این مقاله بحث مربوط تزریق کد در پروسه دیگر مطرح می شود. که در
سایت barnamenevis.org مورد بررسی قرار گرفته بود؛ و من
مطالب اصلی را از این بحث خارج کرده و در این مقاله می گنجانم امیدوارم مورد پسند
شما قرار گیرد.
تعریف:
در ادبيات امنيت نرم افزار ، Process Injection به تزريق كد باينري به فضاي
آدرسي پروسه هاي ديگه گفته ميشود . سيستمهاي عامل مدرني كه از مدل Protected Mode
استفاده ميكنن ، براي هر پروسه با استفاده از تركيب حافظه حقيقي و مجازي ، فضاي
آدرسي مستقلي رو تعريف ميكنن كه اجزاء يك پروسه ( توابع ، متغيرها ، اشاره گر ها ،
رفرنسها ، كتابخانه هاي اشتراكي و ... ) داخل اون فضا آدرس دهي ميشوند . پردازنده ،
به نوبت ، كد ماشين رو بصورت جداگانه از هر فضاي آدرسي دريافت و پردازش ميكنه . اگر
شما كد ماشين يا متغير يا ساير موجوديتهاي باينري مورد نظرتان را ، بدون اينكه بطور
مستقيم متعلق به يك پروسه باشن ، به فضاي آدرسي اون پروسه تزريق كنيد ، يك Process
Injection انجام داده اید.
مثال : شما برنامه A.exe رو نوشته اید . يك برنامه به نام
explorer.exe هم روي ويندوز وجود دارد . شما به هر دليل مايليد يكي از عناصر موجود
در فضاي آدرسي explorer.exe رو توسط A.exe تغيير بديد . Process Injection يعني
تزريق كد مورد نظر از فضاي A.exe به فضاي explorer.exe .
کاربرد:
كاربرد اصلي و عام Process Injection ، توسعهء برنامه هاي مرتبط با Access
Control است . برنامه هاي مثبت ، با استفاده از اين تكنيك و با تزريق يك كد محافظ
به فضاي آدرس پروسه هاي سرور يا سرويس های ( inetinfo.exe يا svchost.exe و ... )
سعي ميكنن اين پروسه ها رو از گزند تلاشهاي مخرب و كدهاي مخرب ( Exploit ) ايمن نگه
دارن . برنامه هاي منفي با استفاده از Process Injection به مقاصد شومي مثل عبور از
فايروالهاي شخصي و فريب دادن آنتي ويروسها خواهند رسيد .
مثال مثبت : زون آلارم(ZoneAlarm) ، با تزريق كد كه
اجراي كد باينري از طريق بخش Data ي Stack رو ممنوع ميكنه ، به داخل فضاي پروسه
هائي مثل Services.exe از اونها نگهداري ميكنه . اين يه نمونه كاربرد مثبت Process
Injection است .
مثال منفي : اغلب فايروالهاي شخصي ، Access Control رو مبتني بر پروسهء فراخوانِ كد
انجام ميدهند . يعني اگر فراخواني كدي از طريق پروسهء قابل اعتماد IExplorer.exe (
مرورگر ويندوز ) انجام شده باشه ، فايروال اجازه ايجاد اتصال شبكه رو ميده و اگر نه
، خير . يك تروجان ، براي اتصال به شبكه ، با وجود يك فايروال شخصي توفيق چنداني
نخواهد داشت ، اما با استفاده از يك Process Injection ساده و تزريق كد باينري مورد
نظر براي ايجاد اتصال شبكه اي ، به فضاي پروسهء IExplorer.exe ميتونه فايروال رو
دور بزنه .
چند نمونه از کاربرد های مختلف آن:
ويندوز 2003 سرور به عنوان يكي از معدود سيستمهاي عاملي كه روي IA32 ميتونه تا
حدود 4 گيگ آدرس دهي بكنه ، هم از Process Injection براي افزايش كيفيت و كارائي اش
استفاده كرده . ويژگي HotPatch موجود در ويندوز 2003 دقيقا" از همين قابليت استفاده
ميكنه . با تشكر از اين تكنيك ، در صورت كشف يك نقطه ضعف امنيتي روي يك سرويس خاص (
مثلا" IIS 6 ) شما براي نصب Patch اون لازم نيست سرويس رو متوقف كنين . Patch با
استفاده از سرويس HotPatch يك نسخه از خودش رو روي Image سرويس در هارد ديسك
بازنويسي ميكنه و يك نسخه از تصحيحات لازم رو بصورت زنده ( Process Injection ) روي
سرويس در حال اجرا و سرويسدهي اعمال ميكنه . به اين ترتيب دفعه بعدي كه سرويس اجرا
ميشه ، از يك نسخه امن استفاده ميكنه مضاف بر اينكه ، همين حالا هم با اعمال زندهء
تغييرات روي نسخهء در حال اجراي سرويس در فضاي آدرسي مخصوص به خودش ، نقطه ضعف
امنيتي بر طرف شده .
مايكروسافت براي كساني كه ميخوان از اين ويژگي بصورت جدي استفاده كنن يك Calss
Library مبتني بر COM به رايگان منتشر كرده كه با جستجو روي سايت مايكروسافت پيداش
ميكني . ( CPP ) .
مثال عملی(دلفی):
{
Process Injection by Inpy - Soul
inprise@gmail-dot-com
Greets to soul for giving me the imagebase idea.
}
program Project1;
{$IMAGEBASE $13140000}
uses
Windows;
//Injected entrypoint
function Main(dwEntryPoint: Pointer): longword; stdcall;
begin
{now we are in notepad}
LoadLibrary('kernel32.dll');
LoadLibrary('user32.dll');
MessageBox(0, 'Hello, now I am in the memory of another process!',
'Hijacked Process', 0);
MessageBox(0, 'Now we can do anything we want. :)', 'Hijacked Process',
0);
MessageBox(0, 'You can even delete the original exe and these message
boxes will still be here.', 'Hijacked Process', 0);
MessageBox(0, 'See?', 'Hijacked Process', 0);
MessageBox(0, 'Told you.', 'Hijacked Process', 0);
MessageBox(0, 'Ok, bye.', 'Hijacked Process', 0);
MessageBox(0, 'Hails to Barnamenevis.org fellas ', 'Hijacked Process', 0);
MessageBox(0, 'I''ll close notepad for you ;)', 'Hijacked Process', 0);
ExitProcess(0);
Result := 0;
end;
//Injection
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
{lets make a new process}
CreateProcess(nil, 'notepad', nil, nil, False, 0, nil, nil, StartupInfo,
ProcessInfo);
{give it some time to wake up}
Sleep(500);
{and hijack it!}
GetWindowThreadProcessId(FindWindow('Notepad', nil), @PID);
ProcessHandle := OpenProcess(PROCESS_ALL_ACCESS, False, PID);
Inject(ProcessHandle, @Main);
CloseHandle(ProcessHandle);
{we have a copy of ourself running in notepad so we can exit}
end.
//go home kid :-) |
توضیح کد:
1.تابع Main در بدنهء پروسهء قرباني اجرا ميشه . نسخه اصلي كد با دريافت نقطه
شروع خودش رو تنظيم ميكنه ليكن انتشارش لزومي نداشت . بعد از ورود به كانتكست پروسه
Notepad چند پيام نمايش داده ميشه كه نشاندهنده موفقيت آميز بودن روند تزريق كد است
2. روتين Inject كد مورد نظر رو تزريق ميكنه . به عنوان ورودي پروسه مورد نظر رو در
نقش قرباني دريافت ، نقطه مناسب براي شروع كد تزريقي رو پيدا و با روشهاي گفته شده
در صفحه قبل فضاي لازم براي ايجاد يك ريسمان راه دور رو به خودش اختصاص ميده .
3. بدنهء اصلي برنامه ابتدا يك نسخه از Notepad به عنوان مثال ميسازه ، شماره پروسه
رو دريافت و به روتين Inject ارسال ميكنه . اين روتين ، تابع Main رو به فضاي آدرسي
Notepad كپي ميكنه . حالا كد ِ در حال اجرا ارتباطي با برنامه ساخته شده توسط ما
نداره و روي حافظه مختص به Notepad اجرا ميشه .
اگر به توضيحات دقت كنيد ميبينيد كه ابتدا هندل پروسه مورد نظرم -
اينجا Notepad - رو بدست آوردم بعد فضاي مورد نظرم رو اختصاص دادم نهايتا" يك
Remote Thread براي اجراي كد مطلوب ايجاد شده است . براي مطالعه بيشتر در مورد
جزئيات و الفباي كاركرد عناصر ويندوز خصوصا" با ديد توسعه كاربردهاي سيستمي و
امنيتي كتاب Windows Internals مارك راشنوويچ از MS
Press رو بخون .
نویسنده:
Inprise
برگرفته از سایت:
www.barnamenevis.org
| |
|