سؤال

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

على سبيل المثال ، لنفترض أنني وجدت فئة تسمى FOO ، مع مُنشئها @ 0x4012d30 ودالة dothemario @ 40125d4. أعلم أيضًا أنه يحمل ثلاثة كلمات من البيانات الخاصة. نظرًا لأن كلتا الطريقتين هي _thiscalls ، أعلنت فئة مثل ذلك في الكود الخاص بي:

class GuessedFoo {
    private:
        int bar;
        char *cafebabe;
        float deadbeef;
    public:
        GuessedFoo(int a, int b);
        void doTheMario();
};

الآن ، هذه فئة مثالية ، ولكن الآن هل هناك أي طريقة لجعل المترجم / الرابط يربط أساليب الفصل بالعنامتين السابقتين اللتين ذكرتهما؟ بالطبع يمكنني كتابة غلاف ASM لتحويل stdcall إلى thisCall لكل طريقة أحتاج إلى استخدامها ، ثم استخدام الهياكل بدلاً من الفصول ، ولكن يجب أن تكون هناك طريقة أفضل.

أستخدم GCC/G ++ في الوقت الحالي ، لكن يمكنني التبديل إلى VC ++ (نظرًا لأن ASM المضمّن من GCC يمنحني الصداع على أي حال).

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

المحلول

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

إذا كان لدى الفصل VTA ، فمن المحتمل أن تصبح الأمور أكثر تعقيدًا ؛ من المحتمل أن تحتاج إلى إنشاء VTABLE بشكل صريح كهيكل من مؤشرات الوظيفة ، وجعل وظيفتك تدعو إليها. هذا يعني وظائف Shim أكثر تعقيدًا ؛ قد لا تكون وظيفة عارية بسيطة مع قفزة كافية ، وقد يكون من الأفضل الذهاب مع وظيفة حقيقية. تذكر ، رغم ذلك ، يعمل هذا العضو على Win32 استخدام أ اتفاقية استدعاء مختلفة; ؛ هذا يعني أن مكالمة وظيفة العضو العادية لن تعمل. أنت مايو كن قادرًا على الابتعاد عن وظائف بناء المؤشرات ، ولكن ضع في اعتبارك أن لديهم أ بنية غريبة إلى حد ما بالنسبة لهم ، وستحتاج إلى مطابقة الأمر بشيء له نفس تمثيل المؤشرات القابلة للتطبيق. حظا طيبا وفقك الله!

نصائح أخرى

أنت منركية عكسية هنا ، وبالتالي (تقريبًا ، ربما) مجبرة على الانخفاض عندما يتعلق الأمر بالتفاعل مع التعليمات البرمجية الحالية.

أود أن أسمي هذه الوظيفة باستخدام رمز التجميع الخالص.
إذا تم إصلاح عنوان قاعدة EXE ، فسيكون الأمر أسهل.
رمز المثال:

void main()
{
    int bar = 5;
    int * cafebabe = &bar;
    __asm
    {
        push [bar];
        push [cafebabe];
        mov eax, 123456; // address of the function
        call eax;
    }
}

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

لست متأكدًا تمامًا من أنني أفهمك بشكل صحيح ، ولكن على أي حال: أعتقد أن أسهل طريق إلى أساليب "التخطيط اليدوي" هو استخدام رميات الوظائف.

لا يحدد C ++ أي نوع من الواجهة الثنائية مما يجعل من المستحيل تنفيذ أي نوع من الربط الديناميكي لفئات C ++.

أفضل ما يمكنك فعله هو إعلان اثنين من البنيتين - واحد يحتوي على وظيفة c typedefs لكل طريقة ، والآخر يعكس تخطيط بيانات الفئة.

بالطبع - نظرًا لأن __thiscall على طريقة الفصل يمر "هذا" عبر سجل ECS ، فأنا لا أؤمن أنه يمكنك في الواقع إصدار إعلان صريح C الذي سيكون له نفس التأثير ، لذلك قد تحتاج إلى إجراء جميع المكالمات عبر مخصص "callthiscallmethodwithparameters" التي كنت تكتبها في التجميع.

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