كيف يمكنني إنشاء الكائنات على أساس ملف تفريغ الذاكرة في WinDbg التمديد ؟

StackOverflow https://stackoverflow.com/questions/2573242

سؤال

أنا أعمل على تطبيق كبير و في كثير من الأحيان استخدام WinDbg لتشخيص القضايا استنادا إلى ملف برنامج إدارة الكوارث من العملاء.كنت قد كتبت بضع صغيرة ملحقات WinDbg التي ثبت أنها مفيدة جدا لسحب بت من المعلومات من DMP الملفات.في تمديد قانون أجد نفسي dereferencing فئة c++ الكائنات في نفس الطريق ، مرارا وتكرارا ، من جهة.على سبيل المثال:

Address = GetExpression("somemodule!somesymbol");
ReadMemory(Address, &addressOfPtr, sizeof(addressOfPtr), &cb);

// get the actual address
ReadMemory(addressOfObj, &addressOfObj, sizeof(addressOfObj), &cb);

ULONG offset;
ULONG addressOfField;

GetFieldOffset("somemodule!somesymbolclass", "somefield", &offset);
ReadMemory(addressOfObj+offset, &addressOfField, sizeof(addressOfField), &cb);

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

هل هذا ممكن ؟ حاولت الأمور واضحة مثل إنشاء كائن جديد في التمديد ، ثم الكتابة مع كبير ReadMemory مباشرة من ملف برنامج إدارة الكوارث.هذا ويبدو أن وضع البيانات في الحقول ، ولكن فزعت عندما حاولت استدعاء دالة.أعتقد أنا في عداد المفقودين شيئا...ربما c++ تسحب بعض vtable غير تقليدي نيس الذي لا أعلم عنه ؟ قانون بلدي تبدو مشابهة لهذه:

SomeClass* thisClass = SomeClass::New();
ReadMemory(addressOfObj, &(*thisClass), sizeof(*thisClass), &cb);

متابعة:يبدو من المحتمل ExtRemoteTyped من EngExtCpp هو ما أريد ؟ وقد أي شخص استخدامها بنجاح من هذا ؟ أريد أن جوجل بعض التعليمة البرمجية الموجودة في المثال ، ولكن لست وجود الكثير من الحظ.

متابعة 2:أنا متابعة اثنين من طرق مختلفة من التحقيق في هذا.
1) أنا أبحث في ExtRemoteTyped ، ولكن يبدو أن هذه الفئة هي في الحقيقة مجرد مساعد على ReadMemory/GetFieldOffset المكالمات.نعم سوف تساعد في تسريع الامور الكثير, ولكن لا يساعد حقا عندما يتعلق الأمر إعادة إنشاء كائن من ملف برنامج إدارة الكوارث.على الرغم من أن الوثائق سليم, لذلك قد يكون سوء فهم شيئا.2) أنا أبحث أيضا في محاولة لاستخدام ReadMemory الكتابة كائن تم إنشاؤه في التمديد مع البيانات من ملف برنامج إدارة الكوارث.ومع ذلك, بدلا من استخدام sizeof(*thisClass) على النحو الوارد أعلاه, كنت أفكر فقط انتقاء عناصر البيانات ، وترك vtables يمسها.

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

المحلول

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

ومع ذلك ، قد تكون قادرة على الحصول على 'الوكيل' وجوه العمل أنه عند استدعاء الوكيل الأساليب التي تجعل المكالمات المناسبة ReadMemory() للحصول على معلومات.هذا يبدو أن يكون عادلة قليلا من العمل ، وكنت أعتقد أنه يجب أن يكون أكثر أو أقل مجموعة مخصصة من رمز لكل فئة أردت أن الوكيل.هناك على الارجح أفضل طريقة للذهاب نحو ذلك, ولكن هذا ما جاء بي من أعلى رأسي.

نصائح أخرى

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

class SomeClassRemote : public SomeClass
{
protected:
    SomeClassRemote (void);
    SomeClassRemote (ULONG inRemoteAddress);

public:
    static  SomeClassRemote *       New(ULONG inRemoteAddress);
    virtual ~SomeClassRemote (void);

private:

    ULONG                   m_Address;

};

و في التنفيذ:

SomeClassRemote::SomeClassRemote (ULONG inRemoteAddress)
{
    ULONG cb;

    m_Address = inRemoteAddress;

    // copy in all the data to the new object, skipping the virtual function tables
    ReadMemory(inRemoteAddress + 0x4, (PVOID) ((ULONG)&(*this) +0x4), sizeof(SomeClass) - 4, &cb);
}

SomeClassRemote::SomeClassRemote(void)
{
}

SomeClassRemote::~SomeClassRemote(void)
{
}

SomeClassRemote* SomeClassRemote::New(ULONG inRemoteAddress)
{
    SomeClassRemote*x = new SomeClassRemote(inRemoteAddress);

    return (x);
}

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

يبدو أنني يجب أن تكون قادرة على templatize هذا بطريقة أو بأخرى...ولكن هناك دائما ويبدو أن بعض السبب في أن كل صنف هو تنفيذها بشكل مختلف قليلا ، على سبيل المثال بعض من لدينا أكثر تعقيدا الكائنات زوجين vtables ، سواء التي يجب تخطيها.

أعلم الحصول على تفريغ الذاكرة دائما وسيلة للحصول على المعلومات لتشخيص لكن مع ETW لها الكثير أكثر سهولة و يمكنك الحصول على المعلومات جنبا إلى جنب مع الاتصال مداخن والتي تشمل نظام المعلومات المكالمات رمز المستخدم.MS قد تم القيام بذلك لجميع منتجاتها بما فيها ويندوز ، VS.NET.

فمن غير تدخلية طريقة التصحيح.لقد فعلت نفس التصحيح لفترة طويلة جدا والآن مع ETW أنا قادرة على حل معظم مشاكل العملاء دون إنفاق الكثير من الوقت داخل المصحح.هذه هي بلدي اثنين سنتا.

اقتربت شيء مماثل عندما القرصنة gdi تسرب التتبع امتداد windbg.اعتدت الخاصة بلبنان حاوية تخزين البيانات في العميل يحتاج إلى وسيلة لاجتياز البيانات من التمديد.انتهى تنفيذ أجزاء من hash_map أنا في حاجة مباشرة على امتداد الجانب باستخدام ExtRemoteTyped التي كانت مرضية ولكن استغرق مني لحظة إلى معرفة ؛ o) هنا هو رمز المصدر.

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