کار با Process ها در API

24 12 2008

سلام، شاید براتون پیش اومده باشه که ویروسی Task Manager شما رو غیر فعال کرده باشه و حتی اجازه دسترسی به Registry ویندوز رو هم ازتون گرفته باشه که نتونین از طریق Registry اونو مجدد فعال کنید. ایده ی این نمونه برنامه هم از این نشعت می گیره که، چند روز پیش ویروسی سیستمم رو آلوده کرد و همانطور که بالا بهش اشاره کردم Task Manager مو هم غیر فعال . مجبور شدم از نرم افزار Process Explorer استفاده کنم تا Process ویروس رو KILL کنم. نهایتا تصمیم گرفتم تا خودم برنامه ای مانند این نرم افزار یا حداقل Task Manager ویندوز بنویسم تا در مواقع ضروری بتونم ازش استفاده کنم ( چون اعتقاد دارم هر برنامه نویس باید خودش نیاز های نرم افزاریشو رفع کنه ).

نمونه در �ال اجرا

نمونه در حال اجرا

بریم سر اصل مطلب و به توضیح نحوه کار نرم افزار بپردازیم، روند کار بدین صورته که ابتدا باید ProcessID تمامی process های در حال اجرا بر روی سیستم رو با استفاده از تابع EnumProcesses بدست بیاریم این تابع یک آرایه از نوع DWORD رو گرفته و پس از اجرا ID ی پروسس های در حال اجرا رو درون آرایه قرار میده.

//------/ Buffer
DWORD dwProcessIDs[1024];
//------/ Enumerate all system processes
EnumProcesses(dwProcessIDs, sizeof(dwProcessIDs), &dwNeeded);

خوب پس از استخراج id  ی هر process، باید Handle پروسس رو با استفاده از id اون بدست بیاریم این کار رو با استفاده از تابع OpenProcess انجام میدیم، وظیفه این تابع برگرداندن Handle یک process با استفاده از id اونه.

//-----/ Open process by process id and get the process handle
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
FALSE, dwProcessIDs[i]);

در ادامه برای اینکه بتونیم نام process مورد نظرمون رو بدست بیاریم به دو تابع دیگه نیاز داریم که یکی برای بدست آوردن Module Handle و دیگری برای گرفتن نام پروسس مورد نظر هستش، که این توابع به ترتیب عبارتند از EnumProcessModules که با گرفتن Process Handle ، میتونه Module Handle رو بر گردونه و دیگری با گرفتن Module Handle نام پروسس رو برمی گردونه.

//-----/ Enumerate each process module
//-----/ then we able to retrieve module name Like EXPLORER.EXE
EnumProcessModules(hProcess, &hModule, sizeof(hModule), &dwCbNeeded);
//-----/ Get module name by process handle and module handle
GetModuleBaseName(hProcess, hModule, szProcessName, sizeof(szProcessName) / sizeof(TCHAR));

خوب در ادامه برای اینکه بتونیم اطلاعاتی در مورد میزان استفاده process از حافظه رو بدست بیاریم باید از تابع GetProcessMemoryInfo این تابع با استفاده از Process Handle ی که در دست داریم یک Struct رو با نام PROCESS_MEMORY_COUNTERS پر می کنه که حاوی اطلاعات مختلفی در رابطه با میزان استفاده process از حافظه است.

//-----/ Process memory information
PROCESS_MEMORY_COUNTERS pmc;
//-----/ Get process memory usage information
//-----/ We need just memory usage by getting PeakWorkingSetSize field of struct
//-----/ ATTENTION : All size fields in the structure calculate as Byte
GetProcessMemoryInfo(hProcess, &pmc, sizeof(pmc));

از اونجایی که ما فقط می خواهیم Memory Usage رو در لیستمون نشون بدیم فقط از فیلد PeakWorkingSetSize این struct استفاده می کنیم.

در پست های بعدی در دارستای تکمیل این نرم افزار نحوه بدست آوردن آدرس یک ماژول و تعداد Handle ها ، Kill و Terminate کردن یک پروسس رو براتون توضیح میدم. پس منتظر پست های بعدی باشید. طبق معمول توضیحات کاملتر همراه با سورس نرم افزار هستش که می تونه بیشتر در یادگیری مطلب کمکتون کنه.

نکته : همراه سورس برنامه دو فایل در پوشه lib وجود داره در صورت کامپایل اون دو فایل رو با استفاده از Drag & Drop به پروژه تون اضافه کنید

برای دانلود سورس کامل برنامه اینجا را کلیک کنید.





Write Your Own Windows Inspector

14 12 2008

سلام، امروز براتون یه نمونه برنامه ی توپ نوشتم که می خوام براتون توضیح بدم، معمولا هر برنامه ای که می نویسم هر کدومش داستانی برا خودش داره، چرا و از کجا شروع شد، هدف چی بود و چی از آب در اومد، همینقدر بدونین که ایده ی اینم از بحث Code injection به ذهنم رسید که اگه خدا بخواد و مطلب Code injection و تموم کنم براتون یک مقاله در این موردم می ذارم. اکثر دوستان برنامه نویس حتما با نرم افزار های Spy++, Winspector, HwndSpy آشنایی دارن، این نرم افزار ها ابزارهای بسیار نابی برای برنامه نویسان سیستم هستن. چرا که هر رخداد و رویدادی که در ویندوز میفته مانیتور می کنن و کمک زیادی در درک نحوه کار سیستم و نرم افزار به برنامه نویسان ارائه میدن. دیشب داشتم با یکی از این ابزار کار می کردم، با خودم گفتم من که این همه امکانات نیاز ندارم، بنابر این تصمیم گرفتم یک برنامه ی کوچولو برا خودم بنویسم که با حرکت ماوس بر روی Window ها و کنترل ها Handle , Control Id و Class name اون ها رو بر گردونه.

نحوه کار خیلی ساده ست، کلیات کار از این قراره که شما Handle ویندو رو بر اساس موقعیت ماوس بر روی Screen با استقاده از تابع WindowFromPoint بدست میارین و سپس به راحتی مشخصات Window مورد نظرتون رو با استفاده از Handle بدست اومده استخراج می کنید. قلب برنامه متد MouseMovementEvent هستش که وظیفش بدست آوردن Handle ویندو و مشخصات مربوط به ویندویی  رو داره که ماوس بر روی اونه.

تصویر زیر نمایش حالت اجرای نرم افزار رو نشون میده که مکان ماوس بر روی یکی از button های پنجره Run هستش و اطلاعات اون ویندو رو نشون میده :

SaberSoft.BitInspector

برای دانلود سورس کامل برنامه اینجا رو کلیک کنید
void MouseMovementEvent(HWND hwndDialog, POINT pt)
{
//----/ Get window handle from mouse location
HWND hwnd = WindowFromPoint(pt);
DWORD processID, threadID;
//----/ Get process id by handle of window that mouse now on it
threadID = GetWindowThreadProcessId(hwnd, &processID);
//----/ We don't want to inspect our process
if (::GetCurrentProcessId() == processID) return;
if (hwndOld == hwnd) return;
//------------------------------------------
//-----/ Clear border of last detected window
if (hwndOld)
HighLightWindow(hwndOld, false);
//-----/ Highlight selected window
HighLightWindow(hwnd, true);
//-----/ Set old window handle by new
hwndOld = hwnd;
TCHAR chr[128];
//-----/ Set handle EDIT
_stprintf(chr, __TEXT("0x%08X"), hwnd);
::SetDlgItemText(hwndDialog, IDC_HANDLEEDIT, chr);
//-----/ Set Control ID
DWORD id = GetWindowLong(hwnd, GWL_ID);
_stprintf (chr, __TEXT("%d"), id);
::SetDlgItemText (hwndDialog, IDC_CTRLIDEDIT, chr);
//-----/ Set Class name
::GetClassName (hwnd, chr, 128);
::SetDlgItemText (hwndDialog, IDC_CLASSEDIT, chr);
}