المساعد الشخصي الرقمي

مشاهدة النسخة كاملة : Api Hook مثال بسيط, Hook للدالة TerminateProcess


B.M.AbdelAziZ
25-02-2009, 08:17 AM
بسم الله الرحمن الرحيم

بإختصار API hook هو التعديل بحيث تستدعى دالتنا بدلا من دالة API

مثال الدالة TerminateProcessمن Help نجد:

BOOL TerminateProcess(
HANDLE hProcess, // handle to the process
UINT uExitCode // exit code for the process
);

لتعريفها في Delphi مثلا بإسم جديد HookeD تكون من الشكل:

Var
HookeD: function(hProcess: THandle; uExitCode: UINT): BOOL; stdcall;


الدالة موجدة في kernel32.dll
نحصل على مكانها بإستخدام الدالة GetProcAddress
لإستخدام GetProcAddress نحتاج handle مقبض المكتبة Kernel32.dll
الذي نحصل عليه بدوره بإستخدام الدالة GetModuleHandle
طبعا إن كانت المكتبة غير موجود بالذاكرة يجب تحميلها بإستخدام الدالة LoadLibrary

h:= GetModuleHandle('kernel32.dll');
if h = 0 then
h:= LoadLibrary('kernel32.dll');
@HookED:= GetProcAddress(h, 'TerminateProcess');


حيث نحصل على عنوان الدالة في HookeD
و h مقبض handle في دلفي ب THandle
نعرف دالتا الجديدة NewOne مثل الدالة القديمة تماما:


function NewOne(hProcess: THandle; uExitCode: UINT): BOOL; stdcall;
begin
//
end;


حان وقت العمل، نغير في برنامجنا في الذاكرة بإستخدام الدالة WriteProcessMemory
طبعا قبل التغيير نحفظ ما نريد تغييره في متغير OldBytes بقرائتها بإستخدام الدالة ReadProcessMemory
لكن ماذا نغير ؟
نغير ما نريد، لكن ماذا نريد ؟
نريد أن تنفذ دالتنا NewOne بدلا من الدالة HookeD التي تمثل الدالة TerminateProcess في ذاكرة برنامجنا
في الأخير كل من الدوال ما هي إلا أوامر في موضع ما في الذاكرة
ولكي تنفذ دالتنا يكفي تغيير الأوامر الأولى بأمر قفز لدالتنا أي JMP بلغة التجميع
و يمكننا أيضا أن نستعمل أمر إستدعاء Call
لكن في حالتنا نستخدم Retرجوع و لنقل لسبب ما لا يهما الأن...
يصبح ما نريد كتابته بالشكل:


Push XXXX
Ret


لمن لا يعرف لغة التجميع، تعني ضع XXXX في stack
ثم عد من حيث أتيت Ret
ْXXXX هو عنوان ما في الذاكرة، أين توجد دالتنا الجديدة
وهنا أكتشث ما يسمى Pointer مؤشر... أمزح
عند تجميع الأمرين فوق يصبحان


68
ْXXXX
C3


مكتوبة بنظام 16 أو Hex
في المجموع 6 حروف أو bytes
68 أمر Push
XXXX مؤشر دالتنا الجديدة
C3 أمر Ret
هممم...
نغير 6 حروف
وقبل تغييرها نحفظ 6 حروف القديمة لإرجاعها فيما بعد، حتى يكون العمل نظيف
لتسهيل الأمور قليلا ننشئ Typeنمط جديد للحروف نسميه مثلا T6Bytes


type
T6Bytes = packed record
P: Byte;
addr: Pointer;
R: Byte;
end;
Var
OldBytes, NewBytes: T6Bytes;


في المتغير NewBytes
P تساوي 69
R تساوي C3
addr مؤشر لا نعرفه إلا وقت التنفيذ
نستخدم الدوال كما هو مكتوب فوق:


if ReadProcessMemory(DWORD(-1),
@HookeD, @OldBytes, SizeOf(OldBytes), Dw) then
begin
NewBytes.P:= $68;
NewBytes.R:= $C3;
NewBytes.addr:= @NewOne;
WriteProcessMemory(DWORD(-1),
@HookeD, @NewBytes, SizeOf(NewBytes), Dw);
end;


نجرب إستدعاء الدالة TerminateProcess في زر مثلا Button نكتب :

TerminateProcess(DWORD(-1), 0);


الأن نكتب الكود السابق الذى يعمل Hook في زر ثاني
ننفذ البرنامج و نجرب أو لا بالضغط على الزر الأول عندها يتوقف عمل البرنامج
أي تم تنفيذ الدالة الأصلية TerminateProcess
الأن نعيد تنفيذ البرنامج لكن نظغط على الزر الثاني لعمل Hook ثم نضغط الزر الأول
لا يحدث شيئ لأنه تم تنفيذ دالتنا الجديدة NewOne و هذا هو المطلوب !
طبعا الدالة NewOne لا تعمل شيئ لأننا لم نكتب بها أي شيئ
يمكننا مثلا عرض رسالة تطلب من المستخدم إن أراد الخروج و في حالة موافته نستدعى الدالة الأصلية TerminateProcess و قبل ذلك نعيد الأمور كما كانت :


if MessageBox(Form1.Handle, 'Close ?', 'API HooK',
MB_YESNO or MB_ICONQUESTION or MB_DEFBUTTON2) = IDYES then
begin
WriteProcessMemory(DWORD(-1), @HookeD, @OldBytes, SizeOf(OldBytes), Dw);
HookeD(hProcess, uExitCode);
end;


وهنا إنتهى هذا المثال البسيط،
بالملف المرفق هذا المثال بدلفي و ملف تنفيذي لمن يريد تجربته

ملاحظة: هذا شرح بسيط من صفر لأصفار..مثله! كتبته من قبل في ArabTeam2000-forum (http://www.arabteam2000-forum.com/index.php?showtopic=95621&st=0&start=0)

kachwahed
25-02-2009, 08:58 AM
بارك الله فيك وجزاك خيرا.
بالمناسبة متى نلجأ إلى API hook ؟ عندما لا يتوفر النظام على الدالة (في حالة تغير النظام) فقط ؟؟؟
شكرا كثيرا.

B.M.AbdelAziZ
25-02-2009, 02:39 PM
هناك حالات كثيرة لاستعمال API Hook ( بطرقه المختلفة)
مثال تريد برمجة قاموس او مترجم فوري، مباشرة بوضع الفارة على اي كلمة في اي برنامج تظهر لك الترجمة، هنا تستخدم Hook لدوال API المسؤولة عن اخراج النصوص مثل TextOut و DrawText غيرها
مثال اخر تريد برمجة برنامج حماية او مضاد فيروسات، هنا تعمل Hook لعدد كبير من الدوال وعند استدعاءها اما تسمح بذلك او تمنعه حسب رغبة المستخدم
فقط فكر في الجملة 'استدعاء دالتي بدلا من دالة النظام' وانظر للافاق المتاحة
والسلام عليكم

Ahmed18
27-02-2009, 12:09 AM
شكرا اخي DeltaAziz
يعني مجرد استدعائي للدالة من المكتبة بعد معرفه عنوانها (مكانها) هذة العملية هي ال API Hook !!

B.M.AbdelAziZ
27-02-2009, 08:11 AM
مجرد استدعائي للدالة من المكتبة بعد معرفه عنوانها
ليس الاستدعاء وانما التغيير لكي تستدعى دالتنا نحن، وهذا ابسط نوع من API Hook لان تاثيرة يكون على برنامجنا فقط، دون باقي البرامج التي تعمل بالذاكرة
باختصار:
Hook = قبض
API Hook = قبض دالة API

الشبح الصغير
02-03-2009, 01:32 PM
السلام عليكم
أود ان أسالك سؤال أخى ؟
هل من الممكن التغيير فى ملف Exe بنفس الطريقة تبع الهووك التى كنت تتحدث عنها أم لا
سؤال ثانى : هل هذا ما يطلق عليه Runtime injection وهى طريقة لجعل الفيروسات تملك صلاحيات
أعلى فى النظام وتختفى من البروسيس (طريقة من طرق الرووت كيت ) ؟

أعذرنى لأنى حديث المعرفة بالدلفى ولكنى كنت مبرمج vb6 وقررت تعلم الدلفى مؤخرا


وشكرا أخوك الشبح الصغير

B.M.AbdelAziZ
03-03-2009, 02:33 PM
هل من الممكن التغيير فى ملف Exe بنفس الطريقة تبع الهووك
نعم، ممكن وهذه قصة اخرى، هذا الموضوع فقط عن التغيير في ذاكرة برنامجنا

هل هذا ما يطلق عليه Runtime injection
لا، هذا Hook اي قبض وليس حقن Injection

AL-MOB4RM3G
03-03-2009, 02:49 PM
اخي ديلتا...

نعم، ممكن وهذه قصة اخرى
هل الطريقة تعتمد تقريبا على نفس الشئ؟

ام انك تقصد بقصة اخرى... يعني انه شئ آخر
يحتاج الى شرح آخر :confused::p:rolleyes:

اذا ما عليك الى شرحه ... الله يبارك فيك

B.M.AbdelAziZ
03-03-2009, 03:04 PM
ام انك تقصد بقصة اخرى...
باختصار التعديل على الملف التنفيذي بحاجة لفهم جيد لبنية الملف التنفيذي Win32 PE
الموضوع عن Hook وبنية PE موضوع اخر

TF6M
21-03-2009, 05:36 PM
السلام عليكم
1- مادا تعني (في داكرة برنامجنا ؟؟) أنا كنت أعتقد ان البرنامج يحمل للداكرة على شكل تعليمات (hex/asm)
و المعالج هو المسؤول عن التشفير و الترجمة يعني أن العنوان كيف يكون مخزن في البرنامج التنفيدي.

و ما الفرق بين مقبض البرنامج و رقم التعريف id

2- في ما يخص 6 وحداة لمادا 6 ؟؟ كقيم hex :
1 byte لـ 63
حجم الدالة ؟؟ أيعني أنها 4 وحدات (يجب هنا أن تكون في نظام 32 بيت ؟؟؟ (32=4))
1 byte لـ c3

ملاحظة : درس قمة شكرا لك .

TF6M
21-03-2009, 06:00 PM
****ا أن أكون لم أثقل عليك بأسئلتي فما باليد حيلة جازاك الله كل خير المهم فقط :

dw -1 لم نقم بتعريفه هل هو إختصار لـ DWord ??
2- لما خصصنا البارامتر الأول للدالة ReadProcessMemory بـ dWord(-1) ؟؟؟

B.M.AbdelAziZ
21-03-2009, 06:59 PM
مادا تعني (في داكرة برنامجنا ؟
عندما ينفذ البرنامج وكانه وحده وكل الذاكرة له وحده
القصد ان ما قمنا به من تعديل لا يؤثر على البرامج الاخرى التي تعمل بنفس الوقت

ما الفرق بين مقبض البرنامج و رقم التعريف id
تقصد Handle و PID
باختصار كلاهما مجرد رقم، PID يكون فريد مدى حياة الProcess
لكل شيئ Handle سواء نافذة او Process أو Thread او...
حتى تفهم اكثر طالع احذ كتب Win32
لمادا 6 ؟
حجم الاوامر المستخدمة للتغيير
5 bytes لامر Push
1 byte لامر Ret
المجموع يساوي 6


dw -1 لم نقم بتعريفه
معرف بالمثال المرفق باول مشاركة

Dw : Dword;


لما خصصنا البارامتر الأول للدالة ReadProcessMemory بـ -1 ؟
يقراء نفسه

TF6M
21-03-2009, 10:23 PM
شكرا ,,

1- إذا يمكننا أن نقوم بتتبع دوال الـ Api إنطلاقا من العنوان المحمل (loadlibrary مقبض) من الـ dll المصدر ؟؟

و بما اننا سنعترضها كالـ hook فبسهولة يمكن رصدها .

2- ألاحظ لما أستعمل فاحص للـ dll ما أنه يعطيني عنوان ثابت لمكان دالة ما (بداخل هدا الـ dll) ما تفسير دلك
لأنه عادة ؟ بكل تحميل او إعادة تحميل لتعليمة ما فإنه يأخذ Offset معين على حسب حالة الذاكرة؟؟

B.M.AbdelAziZ
26-03-2009, 06:40 PM
1-
LoadLibrary تحمل المكتبة DLL لذاكرة البرنامج
GetProcAddress تعطي عنوان اي دالة من تلك المكتبة
2-
عند تحميل المكتبة للذاكرة قد يتم عمل relocations لتفهم اكثر كما قلت لك بردي السابق عليك بمعرفة بنية الملف التنفيذي Win32 PE وكيفية عمله
يمكن ان تبداء بروابط الرد #4 من موضوع كيف يتم ضغط الملفات التنفيدية ؟ (http://www.delphi4arab.com/forum/showthread.php?t=38)
والسلام عليكم

TF6M
26-03-2009, 06:58 PM
شكرا ,,

هادا تعليق أحد الأخوى في منتدى آخر (ما رأيك؟؟):

تضع نقطة توقف على LoadLibrary ومن ثم تحفظ العنوان المسترجع في EAX (عنوان المكتبة بعد تحميلها الى الذاكرة) والذي سيحفظ في مكان ما, تقوم بوضع نقطة توقف عليه عند القراءة لانه سيستخدم فيما بعد مع GetProcAddress .

كنت أظن أنه يمكن دلك سواء بالدلفي أو بالأسمبلي ؟؟

+ في ما يخص المقال جاري المطالعة بارك الله فيك.

B.M.AbdelAziZ
26-03-2009, 07:19 PM
تضع نقطة توقف على LoadLibrary ومن ثم تحفظ العنوان المسترجع في EAX (عنوان المكتبة بعد تحميلها الى الذاكرة) والذي سيحفظ في مكان ما, تقوم بوضع نقطة توقف عليه عند القراءة لانه سيستخدم فيما بعد مع GetProcAddress .

يتحدث عن تنقيح Debugging لمكتبة DLL
ما به ؟ او ما المشكل!

كنت أظن أنه يمكن دلك سواء بالدلفي أو بالأسمبلي ؟؟

يمكن عمل اي شيئ باي لغة

TF6M
26-03-2009, 07:28 PM
شكرا تم تنفيذ الدرس بنجاح و بكل سهولة ,,

ممكن تضع سلسلة دروس في مجال برمجة الدريفر ؟؟ أو على أقل توضيحات أكثر .

khiro.alg
03-08-2010, 01:44 AM
السلام عليكم
بارك الله فيك أخي عزيز
نادرةهي المواضيع مثل هاته
وأتمنى أن أرى المزيد
سأعيد المراجعة:)