جعل أي عملية تعمل مع نظام NTFS للمعاملات: خطوتي الأولى لإنشاء صندوق حماية لنظام Windows

TransactionMaster هناك وحدة نمطية في Windows kernel تكون مسؤولة عن دعم تجميع عمليات الملفات في بعض الكيانات تسمى المعاملة . الإجراءات على هذا الكيان معزولة وذرية: يمكن تطبيقها بجعلها دائمة ، أو يتم التراجع عنها . مريحة للغاية عند تثبيت البرامج ، توافق؟ ننتقل دائمًا من حالة متفق عليها إلى أخرى ، وإذا حدث خطأ ما ، يتم التراجع عن كل التغييرات.


منذ أن علمت بدعم هذه الوظيفة ، كنت أرغب دائمًا في النظر إلى العالم من داخل هذه المعاملات. وأنت تعرف ماذا: لقد وجدت طريقة بسيطة ورائعة حقًا لإنجاح أي عملية داخل معاملة ملف ، لكن هوامش الكتاب ضيقة للغاية بالنسبة له . في معظم الحالات ، لا يتطلب ذلك امتيازات إدارية.


دعنا نتعرف على كيفية عمله وتجربته مع برنامجي وفهم ماهية صناديق الرمل.


مستودع


بالنسبة لأولئك الذين يتوقون لمحاولة: TransactionMaster على جيثب .


نظرية


ظهر دعم للمعاملات NTFS ، أو TxF ، في نظام التشغيل Windows Vista ، وتمكّن من تبسيط الرمز المسؤول بشكل كبير عن الاسترداد من الأخطاء في عملية تحديث البرنامج ونظام التشغيل نفسه. في الواقع ، تم نقل مهمة الاستعادة إلى نواة نظام التشغيل ، والتي بدأت في تطبيق دلالات ACID الكاملة على عمليات الملفات - اسأل فقط.


لدعم هذه التقنية ، تمت إضافة وظائف API جديدة تكرر الوظيفة الحالية ، مضيفة معلمة واحدة جديدة - معاملة. أصبحت المعاملة نفسها واحدة من العديد من الكائنات kernel في نظام التشغيل ، جنبا إلى جنب مع الملفات والعمليات وكائنات المزامنة. في أبسط الحالات ، يتألف تسلسل الإجراءات عند التعامل مع المعاملات من إنشاء كائن معاملة عن طريق استدعاء CreateTransaction ، والعمل مع الملفات (باستخدام وظائف مثل CreateFileTransacted و MoveFileTransacted و DeleteFileTransacted و ما شابه ذلك) ، وتطبيق / استعادة المعاملة باستخدام CommitTransaction / RollbackTransaction .


الآن دعونا نلقي نظرة على بنية هذه الميزات. نحن نعلم أن طبقة واجهة برمجة التطبيقات الموثقة ، من المكتبات مثل kernel32.dll ، لا تنقل التحكم مباشرة إلى kernel لنظام التشغيل ، ولكنها تشير إلى طبقة التجريد الأساسية في وضع المستخدم - ntdll.dll ، والتي تجري بالفعل مكالمة نظام. وهنا تنتظرنا مفاجأة: ببساطة لا يوجد ازدواجية في الوظائف للعمل مع الملفات في سياق المعاملات في Ntdll ، كما هو الحال في النواة .


طبقات API

ومع ذلك ، فإن النماذج الأولية لهذه الوظائف من واجهة برمجة تطبيقات Native لم تتغير منذ زمن سحيق ، مما يعني أنها ستتعلم من مكان آخر في سياق أي معاملة لتنفيذ العملية. لكن من اين؟ الجواب هو أن كل مؤشر ترابط يحتوي على حقل خاص يتم فيه تخزين مؤشر المعاملة الحالية. تسمى مساحة الذاكرة التي توجد بها TEB ، كتلة بيئة التدفق. من الأشياء المعروفة ، يتم أيضًا تخزين رمز الخطأ الأخير ومعرّف الدفق هناك.


وبالتالي ، فإن الوظائف ذات اللاحقة *Transacted بتعيين حقل المعاملة الحالية ، واستدعاء وظيفة مماثلة بدون لاحقة ، ثم استعادة القيمة السابقة. يقومون بذلك باستخدام زوج من RtlGetCurrentTransaction / RtlSetCurrentTransaction من ntdll . يعد رمز الوظائف نفسها واضحًا للغاية ، باستثناء الحالة مع WoW64 ، والتي ستتم مناقشتها أدناه.


ماذا يعني كل هذا بالنسبة لنا؟ من خلال تغيير متغير في ذاكرة العملية ، يمكننا التحكم في سياق المعاملة التي يعمل بها مع نظام الملفات. لا تحتاج إلى تعيين أي اعتراضات ومكالمات دالة اعتراض ، ما عليك سوى توصيل واصف المعاملة إلى العملية الهدف وتصحيح عدد قليل من البايتات في ذاكرته لكل من سلاسل العمليات. هذا يبدو الابتدائية ، دعونا نفعل ذلك!


المزالق


أظهرت التجارب الأولى أن الفكرة قابلة للتطبيق: برنامج Far Manager ، الذي أستخدمه بدلاً من Windows Explorer ، ينجو تمامًا من استبدال المعاملات أثناء التنقل ، ويسمح لك بالنظر إلى العالم في سياقها. ولكن كانت هناك أيضًا برامج تنشئ باستمرار سلاسل عمليات جديدة لعمليات الملفات. وفي السيناريو الأصلي ، هذه فجوة ، لأنه ليس من المناسب للغاية تتبع إنشاء سلاسل الرسائل في عملية أخرى (ناهيك عن حقيقة أن "التأخير" أمر بالغ الأهمية هنا). مثال لتطبيق من الفئة الثانية هو WinFile المنقولة مؤخرًا.


تتبع DLL


لحسن الحظ ، يعد التتبع المتزامن لإنشاء سلسلة الرسائل والتكوين اللاحق للمعاملات لها عنصرًا أساسيًا بالكامل من داخل العملية المستهدفة. يكفي تضمين DLL فيه ، وسيقوم مُحمل الوحدة النمطية باستدعاء نقطة الإدخال الخاصة به مع المعلمة DLL_THREAD_ATTACH كل مرة عند إنشاء سلسلة رسائل جديدة. من خلال تطبيق هذه الوظيفة ، قمت بإصلاح التوافق مع أكثر من عشرة برامج.


* من الناحية الفنية ، لا تعمل المكالمة دائمًا ، ويمكن ملاحظة هذا السلوك في بعض الأحيان في واجهة البرنامج. بالنسبة للجزء الأكبر ، الاستثناءات هي مؤشرات الترابط من تجمع العمل من محمل الوحدة النمطية نفسه. الشيء هو أن مكتبات DLL يتم إخطارها تحت قفل أداة تحميل التشغيل ، وهذا يعني: لا يمكنك تحميل وحدات نمطية جديدة في هذه اللحظة. وتقوم مؤشرات الترابط الخاصة بالجهاز ، كما تعلمون ، بالقيام بذلك بالتوازي مع الوصول إلى نظام الملفات. يتم توفير استثناء لمثل هذه الحالات: إذا حددت THREAD_CREATE_FLAGS_SKIP_THREAD_ATTACH كعلامة عند الاتصال بـ NtCreateThreadEx ، يمكنك تجنب إضافة سلسلة NtCreateThreadEx جديدة إلى مكتبات الارتباط NtCreateThreadEx DLL) الموجودة ، وعلى التوالي ، deadlocks. حول هذا ما يحدث هنا.


إطلاق المستكشف


لا يزال هناك الفئة الثالثة والأخيرة من البرامج التي لا تزال تتعطل عند محاولة جعلها تعمل داخل معاملة. أحد هذه البرامج هو مستكشف Windows. لا يمكنني تشخيص المشكلة بدقة ، لكن التطبيق معقد ، ولا يؤثر التبديل السريع داخل المعاملة كثيرًا. ربما يكون السبب في ذلك أنه يحتوي على العديد من واصفات الملفات المفتوحة ، والتي يتوقف بعضها عن العمل في السياق الجديد. أو ربما هو شيء آخر. في مثل هذه الحالات ، تساعد إعادة تشغيل العملية ، بحيث تعمل من البداية في المعاملة. ثم لا ينبغي أن تنشأ أي تضارب.


وبالتالي ، أضفت القدرة على بدء عمليات جديدة إلى البرنامج ، حيث تم تكوين المعاملة وتتبع التدفقات الجديدة حتى قبل الوصول إلى نقطة الدخول ، أثناء إيقاف العملية مؤقتًا. وأنت تعرف ماذا ، عملت! صواب ، نظرًا لأن Explorer يستخدم كائنات COM خارج العملية بفعالية ، فستتوقف المعاينة عند نقل الملفات. ولكن على خلاف ذلك ، كل شيء مستقر.


ما الأمر مع WoW64؟


يعد هذا النظام الفرعي لإطلاق برامج 32 بت على أنظمة 64 بت أداة مريحة للغاية ، ولكن الحاجة إلى مراعاة ميزاته غالباً ما تعقد برمجة النظام. ذكرت أعلاه أن سلوك Rtl[Get/Set]CurrentTransaction مختلف بشكل ملحوظ في حالة العمليات المماثلة. يكمن سبب ذلك في حقيقة أن مؤشرات الترابط في عمليات WoW64 تحتوي على كتلتين للبيئة. لديهم أحجام مختلفة من المؤشر ، ومن المستحسن الاحتفاظ بها في حالة متناسقة ، على الرغم من أن TEB 64 بت له الأولوية في حالة المعاملات. عندما ننشئ المعاملات عن بعد ، يجب علينا إعادة إنتاج سلوك هذه الوظائف. هذا ليس بالأمر الصعب ، لكن يجب ألا تنسى ذلك ، ويمكن الاطلاع على التفاصيل هنا . أخيرًا ، تحتاج عمليات WoW64 إلى نسخة 32 بت إضافية من DLL التعقب.


القضايا التي لم تحل


لا يُضطر إلى الحزن - السيناريو الأول الذي يتبادر إلى الذهن ، وهو إطلاق مثبتي البرامج في هذا الوضع - قيد التشغيل بعد. أولاً ، لم يتم تكوينه لالتقاط العمليات التابعة في نفس المعاملة. هناك العديد من الحلول هنا ، أنا أعمل على هذا. ولكن إذا قام التطبيق بإنشاء عدة عمليات ، فلا يزال من السابق لأوانه استخدامه مع المعاملات.


ثانياً ، القضية الخاصة بالملفات القابلة للتنفيذ والتي لا وجود لها خارج المعاملة تستحق عناية خاصة. أتذكر أنه كان هناك نوع من الفيروسات الذي قام بخداع مضادات الفيروسات الساذجة بهذه الطريقة: تم تفريغها في إحدى المعاملات ، ثم أطلقت نفسها ، ثم تراجعت عن المعاملة. هناك عملية ، لكن لا يوجد ملف قابل للتنفيذ. يمكن أن تقرر مكافحة الفيروسات أنه لا يوجد شيء للمسح ، وأن تتجاهل التهديد. نحتاج أيضًا إلى العمل على حلول مبتكرة ، لأنه ، لسبب ما ، NtCreateUserProcess (وبالتالي ، CreateProcess ) المعاملة الحالية. بالطبع ، يبقى NtCreateProcessEx دائمًا ، ولكن من المتوقع حدوث الكثير من الضجة لحل مشاكل التوافق. سوف أفكر في شيء ما.


وأين هي صناديق الرمل؟


ألق نظرة على الصورة. هنا ، تُظهر ثلاثة برامج مختلفة محتويات نفس المجلد من ثلاثة معاملات مختلفة. رائع ، أليس كذلك؟


نظرة من داخل المعاملة

ومع ذلك ، فإن برنامجي ليس رملًا بأي حال من الأحوال ، فهو يفتقر إلى تفاصيل مهمة واحدة - حدود الأمان . بالطبع ، هذا لا يمنع بعض الشركات من بيع الحرف المماثلة تحت ستار صناديق رمل كاملة ، عار عليهم ، ماذا يمكنني أن أقول. وعلى الرغم من حقيقة أن هذا يبدو مستحيلًا تمامًا ، كيف يمكننا منع أي برنامج من تغيير متغير في ذاكرتنا حتى لو كنا مصحح أخطاء؟ - لدي خدعة رائعة في المتجر ستسمح لي بإكمال ما بدأت به وإنشاء أول صندوق رمل أعرفه ، والذي لن يتطلب برنامج تشغيل ، ولكنه سوف يعمل على إنشاء نظام الملفات بشكل افتراضي. حتى ذلك الحين ، انتظر التحديثات ، واستخدم Sandboxie وقم بتجربة تقنية AppContainer . شكرا لاهتمامكم


مستودع المشروع على جيثب: TransactionMaster .
نفس المادة باللغة الإنجليزية .

Source: https://habr.com/ru/post/ar485784/


All Articles