DLL injection and Hooking
در اینجا قصد داریم تا در مورد DLL Injection و استفاده از آن برای انجام Inline Hooking در پروسس راه دور را بصورت تئوری توضیح دهیم.
در ویندوز هر پروسس فضای آدرس مجازی مختص به خودش را دارد که در آن می توان هر DLL را در هر زمانی لود یا آنلود کرد. اما این لود و آنلود شدن DLL توسط خود پروسس انجام می گیرد. گاهی وقت ها ما تمایل داریم یک DLL را بدون اینکه پروسس بفهمد در داخل پروسس لود کنیم.دلایل زیادی برای این کار وجود دارد (قانونی و غیر قانونی) . برای مثال یک بدافزار نویس ممکن است بخواهد تا فعالیت های مخربش را با لود کردن یک DLL در یک پروسس قابل اطمینان مخفی کند یا ممکن است بخواهد دستگاه های امنیتی را bypass کند از طرف دیگر یک شخص ممکن است بخواهد عملکرد های برنامه ای را توسعه دهد.
ما در اینجا راه های تزریق code/DLL در داخل یک پروسس راه دور (Remote process) را نشان می دهیم .سپس ما آنرا برای هوک کردن API خاصی در پروسس هدف توسعه می دهیم تا بتوانیم کارهای خودمان را انجام دهیم.
DLL Injection
می شود گفت تقریبا نیمی از بدافزارهای امروزی از code injection برای انجام فعالیت های مخرب استفاده می کنند.
در زیر روش های تزریق DLL را مشاهده می کنید:
• Window hooks (SetWindowsHookEX)
• CreateRemoteThread
• App_Init registry key
• ZwCreateThread or NtCreateThreadEx ? Global method (works well on all versions of windows)
• Via APC (Asynchronous procedure calls
البته برخی ازین روش ها در آخرین نسخه های ویندوز مثل 7/8 کار نمی کنند.دلیلش هم پیاده سازی session separation در این نسخه از ویندوز ها است. بنابراین ما تمرکزمون روی ویندوز ایکس-پی است.
در این مقاله ما از روش CreateRemoteThread که یک روش ساده و پرکاربرد است استفاده می کنیم.
DLL Injection using CreateRemoteThread
عمدتا دو حالت وجود دارد :
1. Inject DLL into a running process
2. Create a process and Inject DLL into it
خوب تابع CreateRemoteThread چه کاری انجام می دهد:
این تابع یک thread را در فضای آدرس مجازی پروسس (virtual address space) دیگر ایجاد می کند و یا به عبارت ساده این یعنی که میتوانیم یک تابع در داخل پروسس دیگری اجرا کنیم.
برای اطلاعات بیشتر به MSDN مراجعه کنید.
HANDLE WINAPI CreateRemoteThread(
__in HANDLE hProcess, -------- 1
__in LPSECURITY_ATTRIBUTES lpThreadAttributes,
__in SIZE_T dwStackSize,
__in LPTHREAD_START_ROUTINE lpStartAddress, ---------2
__in LPVOID lpParameter, ---------3
__in DWORD dwCreationFlags, ---------4
__out LPDWORD lpThreadId
);
پارامترهایی که برای ما مهم هستند:
#1 – handle to the process in which the thread is to be created
#2 – A pointer to function or entry point of the thread that is going to be executed
#3 – parameters to the function
#4 – Creation state of the thread
ما همچنین می دانیم که تابع LoadLibrary توسط کتابخانه kernel32.dll برای لود کردن پویا کتابخانه استفاده میشود و خود kernel32.dll بصورت پیشفرض در هر پروسسی لود شده است. بنابراین ما می توانیم آدرس LoadLibrary را بعنوان پارامتر دوم و پارامترهای این تابع را بعنوان پارامتر سوم (همانطور که در بالا می بینید)استفاده کنیم. به این ترتیب تابع LoadLibrary توسط CreateRemoteThread همراه با پارامترهای خودش در پروسس دیگر اجرا خواهد شد که نتیجه اش لود شدن یک DLL در پروسس دیگر است.
تنها مشکل ما در اینجا این است که پارامتر های LoadLibrary میبایست در پروسس هدف باشند.برای مثال اگر ما از LoadLibrary برای لود کردن "mydll.dll" استفاده کنیم پس نام "mydll.dll" می بایست در پروسس هدف باشد.
برای این کار ما میتوانیم از WriteProcessMemory برای نوشتن در هر پروسسی استفاده کنیم و همچنین میتوانیم فضایی در داخل دیگر پروسس ها توسط VirtualAllocEx اختصاص دهیم. اما قبل از آن ما نیاز به هندل به پروسس مان داریم که می توانیم با OpenProcess یا CreateProcess آنرا بدست بیاوریم.
بنابراین ترتیب کارها به این صورت شد:
• Use OpenProcess or CreateProcess API to get the handle of our target process
• Use VirtualAllocEx to allocate space into our target process
• Use WriteProcessMemory to write our DLL name into our target process
• Use CreateRemoteThread to inject our DLL into our target process
مراحل بالا برای ترزیق DLL مان به یک پروسس کافی است.اگر چه برای تزریق به داخل یک پروسس سیستمی ما باید privilege پروسس را به se_debug تنظیم کنیم اما برای سادگی این قسمت رو نادیده می گیریم.
حال اگر ما روش دومی که در بالا گفتیم یعنی Create a process and Inject DLL into it را بخواهیم پیاده سازی کنیم مراحل زیر را باید انجام دهیم.
ابتدا باید یک پروسس توسط CreateProcess ایجاد کنیم سپس از روش هایی که در بالا توضیح دادیم استفاده کنیم.
BOOL WINAPI CreateProcess(
__in_opt LPCTSTR lpApplicationName,
__inout_opt LPTSTR lpCommandLine,
__in_opt LPSECURITY_ATTRIBUTES lpProcessAttributes,
__in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes,
__in BOOL bInheritHandles,
__in DWORD dwCreationFlags, -------- 1
__in_opt LPVOID lpEnvironment,
__in_opt LPCTSTR lpCurrentDirectory,
__in LPSTARTUPINFO lpStartupInfo,
__out LPPROCESS_INFORMATION lpProcessInformation
);
در اینجا مهمترین پارامتر dwCreationFlags است که از آن برای کنترل ساختن یک پروسس استفاده می شود. ما می توانیم آنرا با CREATE_SUSPENDED تنظیم کنیم تا یک پروسس در حالت suspend ایجاد کرده باشیم.
مراحلی که باید طی کنیم:
1. Create Process in suspended state
2. Inject DLL into the process using above steps
3. Resume the process
Hooking
تعریف Hooking در ویکی پدیا:
In computer programming, the term hooking covers a range of techniques used to alter or augment the behaviour of an operating system, of applications, or of other software components by intercepting function calls or messages or events passed between software components. Code that handles such intercepted function calls, events or messages is called a "hook"
هوک یکی از روش های قوی و پراستفاده در نرم افزارهای کامپیوتری است.
اصولا هوک ها را می توان به دو دسته تقسیم کرد:
1. User mode hooks
1. IAT (Import Address Table) Hooking
2. Inline Hooking
3. Call Patching in binary etc..
2. Kernel Mode hooks
1. IDT Hooking
2. SSDT Hooking etc..
که در اینجا ما روش Inline hooking رو مورد بررسی قرار میدیم که یک روش تاثیرگذار و پرکاربرد است.
در Inline hooking ما 5 بایت اول یک تابع یا API را برای تغییر مسیر جریان اجرا به سمت کد خودمان بازنویسی می کنیم.این 5 بایت می تواند دستورات JMP, PUSH RET or CALL باشد.
شکل های زیر گویای روش کار هستند:
فراخوانی عادی (قبل از هوک)
فراخوانی بعد از هوک
همانطور که در شکل بالا مشاهده می کنید بایت های ابتدای تابع MessageBox با دستور JMP به تابع MyHandler بازنویسی شده است.در تابع MyHandler کار دلخواهمون انجام می شود سپس کنترل به تابع اصلی یعنی همان MessageBox برگردانده می شود.
حالا اجازه بدهید یک DLL ایجاد کنیم که MessageBox را هوک کند و پیغام خودمان را بجاری پیغام اصلی نمایش بدهد.
برای ساختن یک DLL ما نیاز به این چیزها داریم:
1. MessageBoxA API address i.e pointer
2. Our function or code address i.e pointer
ما می توانیم آدرس MessageBoxA با استفاده از GetProcAddress بدست بیاوریم.
مراحل کار:
1. Get MessageBoxA address
2. Get custom code or function address
3. Overwrite bytes at #1 with JMP to #2
4. Modify the parameter of original call
5. Transfer control back to #1
اگر مشکل یا سوالی بود بپرسید.
موفق باشید.
Pcrlth0n
سلام قربان خوب هستین؟
عارضم خدمتتون که یه سوالی داشتم
سوالم این هست که میشه یه تابع توی ویندوز (مثلا CreateFile) رو به طوری هوک کرد که هرپروسسی ازش استفاده کرد بفهمیم؟
اگر جوابتون این هست که میتونیم کل پروسس هارو dll injection کنیم باید خدمتتون بگم که توی آنتی ویروس ها و یا برنامه هایی که اصلا دیده نمیشن این روش شدنی نیست
پس در نتیجه باید دنبال روشی باشیم که بتونیم کل پروسس هایی که از این تابع استفاده میکنن رو ببینیم
راهنمایی شما چیه برای اینکار؟
با تشکر