سؤال

تحديث: Microsoft لم تصلحه بعد في Windows 8.1.

تعديل: اتضح أن هذا أ حشرة في WOW64 - قد يعيد GetThReadContext () محتويات قديمة عندما يتم تعليق مؤشر الترابط في وضع Long Mode Ring -3 (وضع المستخدم). لقد اقترحت على Microsoft استخدام Ring-2 لأداء الترجمة. لن يقوم التعليق بعد ذلك بتعليق الخيط فقط في Ring-3 (كما هو الحال الآن-لا توجد تغييرات ضرورية) ، ولن يؤثر التصادم/الخطأ/الاستغلال في الحلقة 2 على kernel-سيؤثر فقط على الحلقة 2 والحلقة- 3.

مثل هذه التغييرات قد تتطلب تغيير بعض وظائف Winapi مثل WOW64GET/SETTHREADCONTEX وما إلى ذلك ، وهذا من شأنه أن يكسر التطبيقات التي تعتمد على الميزات غير الموثقة ولكن هذا متوقع. من المسلم به أن الترجمة ستكون أبطأ لأنها تتطلب بعض دورات وحدة المعالجة المركزية للانتقال من الحلقة -3 إلى الحلقة 2 (اعتمادًا على عائلة وحدة المعالجة المركزية) ، لكنني أعتقد أن دور نظام التشغيل هو أولاً وقبل كل شيء لضمان التشغيل الصحيحة. تضيف الترجمة بالفعل النفقات العامة إلى التطبيقات التي تعمل تحت WOW64 ، لذلك من المتوقع أيضًا.

آمل أن تقوم Microsoft بإصلاح هذه المشكلة - وإلا فإن Defuggers / Mono Apps / Boehm GC / Apps التي تعتمد على getThreadContext () تحت WOW64 لن تعمل (بالنسبة للمبتدئين ، رأيت أصحاب التصريف يظهرون تتبعًا Stack Stack).

EDIT2: اخبار سيئة. من محادثتي مع Alexey من MSFT (هنا) يبدو الأمر كما لو أنه قد لا يتم إصلاحه على الإطلاق في خوف من أن الإصلاح سيؤدي إلى كسر التطبيقات التي تعتمد على الميزات غير الموثقة.


السؤال الأصلي

  • يبدو أن بعض الناس يشعرون بالارتباك بشأن ما يلي. لقد اعتقدت في البداية أنه كان من المقرر أن يعلق SupendThread موضوعًا أثناء وجوده في رمز وضع kernel. لم يكن. ما يلي هو مجرد شكوكي الأولية التي تبين أنها لا علاقة لها بالسبب الجذري الفعلي - الذي كان المحتويات التي تم إرجاعها بواسطة GetThreadContext().

من MSDN:

Suspending a thread causes the thread to stop executing user-mode (application) code.

ومع ذلك ، فإن ما وجدته هو أن تطبيقي 32 بت في Windows 7 يعمل تحت WOW64 ، الخيط A Calling SuperThread على الموضوع B يمكنه إيقاف تشغيله أثناء تشغيل رمز 64 بت (الذي أتوقعه هو ليس رمز وضع المستخدم). يعرض EIP توقف الخيط المعلق عند

wow64cpu!X86SwitchTo64BitMode:
00000000`759c31b0 ea27369c753300  jmp     0033:759C3627

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

أيضًا ، تأكدت من النجاح من خلال التحقق من (DWORD) -1.

كل هذه تقودني إلى الاعتقاد بأن الخيط يتم تعليقه في رمز وضع النواة.

ما الذي يمكن أن يسبب نظام التشغيل لتعليق موضوع أثناء تشغيل رمز غير مستخدم؟ كيف يمكنني منع ذلك؟ هذا يمنعني بشكل أساسي من الحصول على مؤشر المكدس الحالي الفعلي للموضوع ب.

هل كانت مفيدة؟

المحلول

لقد أكدت أن هذه مشكلة في نظام التشغيل تعود إلى محتويات قديمة عندما يتم استدعاء GetThreadContext تحت WOW64.

مزيد من المعلومات هنا.

شكرا لكل من حاول الإجابة على هذا السؤال. أنا أعمل مع مرض التصلب العصبي المتعدد لحل هذا.

نصائح أخرى

انظر هذا التفسير: getThreadContext في wow64

تشرح هذه المقالة أن الانتقال بين أوضاع X86 و AMD64 يتم في وضع المستخدم.

ماذا يفعل موضوعك في وضع المستخدم؟ يبدو أنه موجود بالفعل في وضع kernel عند الاتصال SuspendThread. هل من الممكن تنفيذ وظيفة النظام في اللحظة التي تعلقها؟

ما الذي يمكن أن يسبب نظام التشغيل لتعليق موضوع أثناء تشغيل رمز غير مستخدم؟

قد تؤدي العديد من مكالمات النظام أو المكتبة إلى التبديل إلى وضع kernel. ولأن kernel Windows مصمم لإعادة الدخول في معظم الحالات ، فإن التحول من مؤشر ترابط إلى آخر بينما يكون الأول في وضع kernel أمرًا طبيعيًا جدًا.

كيف يمكنني منع ذلك؟

مجرد فكرة: قم بإنشاء موضوع يقوم فقط بتنفيذ حلقة فارغة (على سبيل المثال for(;;);) وتعليق هذا الموضوع. لا ينبغي تعليق هذا واحد في وضع النواة.


أيضا ، لماذا من المهم بالنسبة لك أن سجلات ESP وما إلى ذلك صحيحة؟ أتمنى أن تكتب نوعًا من الأخطاء أو شيء مرتبط ، لأن هذا ما SuspendThread هو ل.

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

Beisdes ، يجب ألا تعبث بهذا. سيكون هذا خطأ في نظام التشغيل إذا كان يمكنك (في وضع المستخدم) التحكم في ما إذا كان تم تنفيذ رمز وضع kernel.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top