-9
إخواني الأعزاء السلام عليكم.
أولا أود أن أهنئكم على افتتاح هذا القسم الذي أرجو أن يعج بمشاركاتكم و استفساراتكم.
ثانيا أحببت أن أشارك بكتابة هذا الموضوع المتواضع عن دوال مكتبة الأدوات المساعدة Tool Help Library فأرجو أن يلقى إعجابكم.
هذا الموضوع ليس لبرنامج متقدم و إنما موضوع اخباري و يهم المبتدئين قبل المحترفين.
مقدمة:
تساعد دوال مكتبة الأدوات المساعدة Tool Help Library المطورين على الحصول على معلومات حول التطبيقات جارية التنفيذ على الجهاز Processes. وتحتوي هذه المكتبة على اثنتا عشر دالة، و يتم استخدام هذه الدوال مثلا في برامج التنقيح كبرنامج Task Manager .
هذه الدوال هي:
CreateToolhelp32Snapshot
Heap32First
Heap32ListFirst
Heap32ListNext
Heap32Next
Module32First
Module32Next
Process32First
Process32Next
Thread32First
Thread32Next
Toolhelp32Read
ProcessMemory
سأتطرق لثلاثة من هذه الدوال و سأضيف تطبيقات لهم حتى يتسنى للقراء استيعاب أكثر.
1 - الدالة CreateToolhelp32Snapshot و هي الأهم.
تقوم هذه الدالة بأخذ لقطة Snapshot أو صورة تحتوي على معلومات تتعلق بالتطبيقات جارية التنفيذ processes وأيضا المراكم heaps و الوحدات modules (متلا مكتبات (DLL و الخيوط threads المستعملة من طرف هذه التطبيقات.
تعريف:
HANDLE WINAPI CreateToolhelp32Snapshot(DWORD dwFlags, DWORD th32ProcessID);
المعطيات:
dwFlags -a
يقبل قيما تسمى رايات، تقوم بتحديد المعلومات التي نريد الحصول عليها، هذه القيم معرفة كالتالي:
TH32CS_SNAPPROCESS : تحديد قائمة جميع التطبيقات جارية التنفيذ.
TH32CS_SNAPTHREAD : تحديد قائمة جميع الخيوط جارية التنفيذ.
TH32CS_SNAPHEAPLIST : تحديد قائمة المراكم لتطبيق جاري التنفيذ.
TH32CS_SNAPMODULE : تحديد قائمة الوحدات لتطبيق جاري التنفيذ.
TH32CS_SNAPALL : تكافئ تحديد كل هذه القيم TH32CS_SNAPHEAPLIST و TH32CS_SNAPMODULE و TH32CS_SNAPPROCESS و TH32CS_SNAPTHREAD.
th32ProcessID -b
يأخذ قيمة معرِّف تطبيق جاري التنفيذ ProcessID فقط عند استعمال TH32CS_SNAPMODULE و TH32CS_SNAPMODULE في المعطى الأول، أو يأخذ القيمة 0 فيما عدا ذلك.
القيمة المعادة:
في حالة نجاح الدالة تقوم بإرجاع مقبض للقطة Snapshot التي تم إنشاؤها والتي تحمل المعلومات التي قمنا بتحديدها بواسطة المعطيات الممررة، أما في حالة أي خطأ تقوم الدالة بإرجاع العدد 1-.
و لكي نستفيد من المعلومات التي تحتويها هذه اللقطة Snapshot نقوم باستخدام الدوال الأخرى لتفحصها و استخراج المعلومات منها.
ملحوظة : المعلومات الموجودة في اللقطة Snapshot هي للقراءة فقط.
عند الانتهاء من اللقطة Snapshot نقوم باستدعاء الدالة CloseHandle لتحرير مساحة الذاكرة التي تشغلها هذه اللقطة.
2 - الدالة Process32First
تقوم بأخذ المعلومات المتعلقة بالتطبيق جاري التنفيذ(Process) الأول المصادَفة في اللقطة، ووضعها في حقول تسجيل أو بنية struct .
تعريف:
BOOL WINAPI Process32First(HANDLE hSnapshot, LPPROCESSENTRY32 lppe);
المعطيات :
hSnapshot -a
مقبض اللقطة التي تم إنشاؤها سابقا.
Lppe -b
عنوان البنية PROCESSENTRY32 التي يتم وضع المعلومات داخلها.
القيمة المعادة:
تقوم الدالة بإرجاع القيمة TRUE في حالة نجاحها بنقل المعلومات المتعلقة بالتطبيق جاري التنفيذ الأول ووضعها في حقول البنية، أو FALSE في حالة فشلها.
ملحوظة: قبل استدعاء هذه الدالة يجب أن تضع في الحقل dwSize للبنية PROCESSENTRY32 قيمة سعة هذه البنية (sizeof(PROCESSENTRY32 .
لاسترجاع معلومات التطبيق جاري التنفيذ التالي نقوم باستدعاء الدالة Process32Next.
3 - البنية PROCESSENTRY32
typedef struct tagPROCESSENTRY32 {
DWORD dwSize;
DWORD cntUsage;
DWORD th32ProcessID;
DWORD th32DefaultHeapID;
DWORD th32ModuleID;
DWORD cntThreads;
DWORD th32ParentProcessID;
LONG pcPriClassBase;
DWORD dwFlags;
char szExeFile[MAX_PATH];
} PROCESSENTRY32;
4 - الدالة Process32Next
تقوم باسترجاع المعلومات المتعلقة بالتطبيق جاري التنفيذ التالي المصادَفة في اللقطة، ووضعها في حقول البنية PROCESSENTRY32 .
المعطيات :
hSnapshot -a
مقبض اللقطة التي تم إنشاؤها سابقا.
Lppe -b
عنوان البنية PROCESSENTRY32 التي يتم وضع المعلومات داخلها.
القيمة المعادة:
تقوم الدالة بإرجاع القيمة TRUE في حالة نجاحها بنقل المعلومات المتعلقة بالتطبيق جاري التنفيذ التالي ووضعها في حقول البنية، أو FALSE في حالة فشلها.
والآن بعد هذه المطالعة القصيرة سنقوم بإنشاء تطبيق يقوم بسرد أسماء التطبيقات جارية التنفيذ(Processes) .
سأقوم بكتابة الكود بلغة باسكال تحت بيئة Delphi فإن كنت لا تعرف هذه اللغة فلا تقلق سأقوم بشرح التعليمات حتى يتسنى لك ترجمتها إلى اللغة التي تريد.
تطبيق 1:
1 - لكي نقوم بسرد أسماء التطبيقات جارية التنفيذ (Processes) يجب أن نأخذ لقطة لها وذلك باستدعاء الدالة CreateToolhelp32Snapshot و أن نمرر لها المعطيان TH32CS_SNAPPROCESS و 0 كما هو مبين في الشرح أعلاه، ثم نضع الناتج أي مقبض اللقطة hSnapShot الذي سنحتاجه فيما بعد في متغير وسعه 4byte .
hSnapshot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
يجب أن نعرف المتغير hSnapshot.
var hSnapshot: THandle;
THandle = LongWord و LongWord عدد صحيح موجب يمتد بين 0 و 2^32 .
يوجد منكم من سيقول أن الدالة تعيد قيمة سالبة وهي 1- ، لذاك سنستعمل القيمة $FFFFFFFF المكافئة ل 1-.
2 - في حالة فشل الدالة ننهي البرنامج.
سنقوم باستدعاء الدالة Halt لتقوم بإنهاء البرنامج في حالة فشل الدالة السابقة.
If hSnapshot = $FFFFFFFF then Halt(0);
3 - يجب أن نتفحص معلومات اللقطة باستعمال الدالتين Process32First و Process32Next، ولكن قبل ذلك نقوم بتعريف البنية التي ستحوي هذه المعلومات.
var ProcessEntry: TProcessEntry32;
TProcessEntry32 = tagPROCESSENTRY32 فإن لم تكن هذه البنية معرفة في بيئتك البرمجية فقم بتعريفها بنفسك.
سنقوم بإعطاء قيمة أولية للحقل dwSize وهي سعة البنية.
ProcessEntry.dwSize := SizeOf(ProcessEntry);
بعد ذلك نستدعي الدالة Process32First التي ستقوم بنقل المعلومات المتعلقة بالتطبيق جاري التنفيذ(Process) الأول المصادَفة في اللقطة ووضعها في حقول البنبة ProcessEntry ، ثم بعد ذلك نقوم باستخراج الاسم.
if Process32First(hSnapshot, ProcessEntry) then begin Writeln(ProcessEntry.szExeFile); end;
الحقل szExeFile بحتوي اسم التطبيق جاري التنفيذ(Process) الأول بعد ملئه من طرف الدالة Process32First
الدالة Writeln تقوم بإخراج الاسم إلى الشاشة.
والآن مادامت هناك معلومات حول تطبيقات جارية التنفيذ أخرى سنقوم بتفحصها باستعمال الدالة Process32Next ووضعها في حقول البنبة ProcessEntry ، ثم استخراج الاسم منها.
while Process32Next(hSnapShot, ProcessEntry) do Writeln(ProcessEntry.szExeFile);
لقد انتهينا من سرد أسماء التطبيقات جارية التنفيذ، والآن يجب علينا تحرير مساحة الذاكرة التي تشغلها اللقطة.
CloseHandle(hSnapShot);
الكود كامل:
program Project1;
{$APPTYPE CONSOLE}
uses
//SysUtils,
TlHelp32,
Windows;
var
hSnapshot: THandle;
ProcessEntry: TProcessEntry32;
begin
hSnapshot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if hSnapshot = $FFFFFFFF then Halt(0);
ProcessEntry.dwSize := SizeOf(ProcessEntry);
if Process32First(hSnapshot, ProcessEntry) then
begin
Writeln(ProcessEntry.szExeFile);
while Process32Next(hSnapshot, ProcessEntry) do
Writeln(ProcessEntry.szExeFile);
end;
CloseHandle(hSnapshot);
Readln;
end.
تطبيق 2 :
هذا التطبيق يقوم بسرد أسماء ومسارات الوحدات ( مكتبات (DLL التي يستعملها.
program Project2;
{$APPTYPE CONSOLE}
uses
//SysUtils,
TlHelp32,
Windows;
var
hSnapshot: THandle; // تعريف مقبض اللقطة
ModuleEntry: TModuleEntry32; // تعريف البنية الخاصة بمعلومات الوحدات
begin
//إنشاء اللقطة
hSnapshot := CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId);
//نقوم بإنهاء البرنامج في حالة فشل الدالة السابقة
if hSnapshot = $FFFFFFFF then Halt(0);
//وهي سعة البنية dwSize نقوم بإعطاء قيمة أولية للحقل
ModuleEntry.dwSize := SizeOf(ModuleEntry);
//ModuleEntry نقوم بنقل المعلومات المتعلقة بالوحدة الأولى المصادَفة في اللقطة ووضعها في حقول البنية
if Module32First(hSnapshot, ModuleEntry) then
begin
//szExePath و szModule إخراج اسم ومسار الوحدة إلى الشاشة الموجودان في الحقلين
Writeln(ModuleEntry.szModule + ' - "' + ModuleEntry.szExePath + '"');
//مادام هناك وحدات أخرى أخرج أسماءها ومساراتها إلى الشاشة
while Module32Next(hSnapshot, ModuleEntry) do
Writeln(ModuleEntry.szModule + ' - "' + ModuleEntry.szExePath + '"');
end;
//تحرير مساحة الذاكرة التي تشغلها اللقطة
CloseHandle(hSnapshot);
Readln;
end.تطبيق 3 :
سنقوم بإنشاء دالة تقوم بإنهاء تطبيق جاري التنفيذ معين وذلك بتمرير اسمه للدالة.
في حالة نجاح هذه الدالة تعيد لنا القيمة True .
إذن تعريف هذه الدالة سيكون على الشكل التالي
function TerminateTask(exeFileName: string): Boolean;
لكي ننهي تطبيق جاري التنفيذ معين نحتاج إلى الدالة TerminateProcess . هذه الدالة تحتاج معطيين، الأول هو مقبض التطبيق جاري التنفيذ hProcess و كود الخروج uExitCode الذي سنعطيه القيمة 0 .
سؤال : كيف نستطيع الحصول على مقبض تطبيق جاري التنفيذ معين بدلالة اسمه.
لكي نحصل على مقبض تطبيق جاري التنفيذ معين نحتاج إلى الدالة OpenProcess . هذه الدالة تحتاج ثلاث معطيات، الأول هو راية تحدد صلاحيات التعامل مع التطبيق جاري التنفيذ dwDesiredAccess، الثاني bInheritHandle يحدد إمكانية وراثة المقبض أم لا، والثالث هو معرف التطبيق جاري التنفيذ dwProcessId المراد مقبضه.
نعلم أن أسماء ومعرفات التطبيقات جاري التنفيذ نستطيع الحصول عليهما بأخذ لقطة باستعمال الدالة CreateToolhelp32Snapshot إذن فقد حللنا المشكل.
أولا نقوم تفحص اللقطة و مقارنة المعطى exeFileName مع أسماء التطبيقات جاري التنفيذ الواردة في اللقطة،
فإن وجدنا ضالتنا نقوم بأخذ المعرف dwProcessId المكافئ للاسم و نمرره للدالة OpenProcess التي بدورها تعيد لنا المقبض hProcess، هذا المقبض نمرره للدالة TerminateProcess لكي تقوم بإنهاء التطبيق جاري التنفيذ صاحب هذا المقبض.
function TerminateTask(exeFileName: string):Boolean; var hSnapshot: THandle; ProcessEntry: TProcessEntry32; Loop: Boolean; hProcess: THandle; begin Result := False; //إنشاء اللقطة hSnapshot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); //False الخروج من الدالة في حالة فشل الدالة السابقة معيدين القيمة if hSnapshot = $FFFFFFFF then begin Result := False; Exit; end; //وهي سعة البنية dwSize نقوم بإعطاء قيمة أولية للحقل ProcessEntry.dwSize := SizeOf(ProcessEntry); //ProcessEntry نقوم بنقل المعلومات المتعلقة بالوحدة الأولى المصادَفة في اللقطة ووضعها في حقول البنية Loop := Process32First(hSnapshot, ProcessEntry); while Loop do begin //مع أسم التطبيق جاري التنفيذ الوارد في اللقطة exeFileName مقارنة المعطى if UpperCase(exeFileName) = UpperCase(ProcessEntry.szExeFile) then begin //hProcess استرجاع مقبض التطبيق جاري التنفيذ المراد إنهاؤه و وضعه في hProcess := OpenProcess(PROCESS_ALL_ACCESS, False, ProcessEntry.th32ProcessID); //إنهاء التطبيق جاري التنفيذ المراد إنهاؤه و إعادة قيمة نجاح أو فشل العملية Result := TerminateProcess(hProcess, 0); //الخروج من الحلقة Break; end; //العودة إلى الحلقة مادام هناك المزيد Loop := Process32Next(hSnapshot, ProcessEntry); end; //تحرير مساحة الذاكرة التي تشغلها اللقطة CloseHandle(hSnapshot); end;
للمهتمين ببرامج أحصنة طروادة Trojan يمكنكم استخدام هذه الدالة في برمجة الخادم Server وذلك بتمريرلها أسماء مكافحات الفيروسات و الجدران النارية Firewalls لتقوم بإنهاء عملهم.
يمكنكم تحميل الأكواد من المرفقات.
لقد انتهيت، أرجو أنكم استفدتم و استمتعتم بهذا الموضوع.
إليكم خالص تمنياتي بالتوفيق، و السلام عليكم.