سؤال

لقد وجدت هذه الأسطر القليلة من التجميع في Ollydbg:

MOV ECX,DWORD PTR DS:[xxxxxxxx] ; xxxxxxxx is an address
MOV EDX,DWORD PTR DS:[ECX]
MOV EAX,DWORD PTR DS:[EDX+116]
CALL EAX

هل يمكن لشخص ما أن يخبرني بما يحدث هنا؟

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

المحلول

هذا هو الاحتجاج لمؤشر الوظيفة المخزنة في البنية.

يحصل هذا السطر الأول على مؤشر مخزن على العنوان DS:xxxxxxxx. تشير الأقواس المربعة dereferencing من العنوان ، مثل الكثير * في C. القيمة من الذاكرة على وشك استخدامها كمؤشر ؛ يتم وضعه في ecx تسجيل.

MOV ECX,DWORD PTR DS:[xxxxxxxx] ; xxxxxxxx is an address

السطر الثاني يخلط المؤشر الذي تم الحصول عليه أعلاه. هذه القيمة من ecx يستخدم الآن كعنوان ، وهو أمر غير مرغوب فيه. القيمة الموجودة في الذاكرة هي مؤشر آخر. يتم وضع هذا المؤشر الثاني في edx تسجيل.

MOV EDX,DWORD PTR DS:[ECX]

السطر الثالث مرة أخرى خلل الذاكرة ؛ هذه المرة ، يحدث الوصول إلى العنوان عوض من المؤشر الذي تم الحصول عليه أعلاه بواسطة بايت 0x116. هذا ليس قابلًا للقسمة بالتساوي من قبل أربعة ، لذلك لا يبدو أن مؤشر الوظيفة هذا يأتي من VTable C ++. القيمة التي تم الحصول عليها من الذاكرة يتم تخزينها هذه المرة في السجل eax.

MOV EAX,DWORD PTR DS:[EDX+116]

أخيرًا ، أشارت الوظيفة إلى eax يتم تنفيذ. هذا ببساطة يستدعي الوظيفة عبر مؤشر الوظيفة. يبدو أن الوظيفة تأخذ وسيطات صفر ، لكن لدي سؤال حول مراجعة إجابتي: هل هناك PUSH التعليمات التي تسبق هذا المقتطف؟ هذه ستكون حجج الوظيفة. تشير علامات السؤال إلى أن هذه الوظيفة قد تُرجع قيمة ، لا يمكننا معرفة ذلك من Vantage.

CALL EAX

بشكل عام ، يبدو مقتطف الكود وكأنه استدعاء لوظيفة تمديد من مكتبة المكونات إلى Ollydbg. يحدد Ollydbg ABI مختلفًا structS التي تحتوي على بعض مؤشرات الوظائف. هناك أيضًا صفائف من مؤشرات الوظائف ، ولكن التوجيه المزدوج للوصول إلى edx-مؤشر هائل (أيضًا إزاحة غير محاذاة من قبل مواجهة) يجعلني أعتقد أن هذا أ struct وليس مجموعة من مؤشرات الوظائف أو فئة C ++ VTABLE.

بعبارات أخرى، xxxxxxxx هو مؤشر لمؤشر إلى struct يحتوي على مؤشر وظيفة.

في ملحق ملف Ollydbg Source Plugin.H بعض المرشحين struct تعريفات. هذا مثال:

typedef struct t_sorted {              // Descriptor of sorted table
  char           name[MAX_PATH];       // Name of table, as appears in error
  int            n;                    // Actual number of entries
  int            nmax;                 // Maximal number of entries
  int            selected;             // Index of selected entry or -1
  ulong          seladdr;              // Base address of selected entry
  int            itemsize;             // Size of single entry
  ulong          version;              // Unique version of table
  void           *data;                // Entries, sorted by address
  SORTFUNC       *sortfunc;            // Function which sorts data or NULL
  DESTFUNC       *destfunc;            // Destructor function or NULL
  int            sort;                 // Sorting criterium (column)
  int            sorted;               // Whether indexes are sorted
  int            *index;               // Indexes, sorted by criterium
  int            suppresserr;          // Suppress multiple overflow errors
} t_sorted;

هذه الأمثلة مسموح لها أن تكون NULL, ، ومقتطف ASM الخاص بك لا يتحقق NULL مؤشر في مؤشر الوظيفة. لذلك ، يجب أن يكون DRAWFUNC من t_table أو SPECFUNC من t_dump.

يمكنك إنشاء مشروع صغير يتضمن ملف الرأس والاستخدامات printf() و offsetof() لتحديد ما إذا كان أي من هذين في إزاحة 0x116.

خلاف ذلك ، أتصور أن الدواخل من Ollydbg مكتوبة في هذا النمط نفسه. لذلك من المحتمل أن تكون خاصة struct التعريفات (غير المنشورة في ملف البرنامج المساعد) المستخدمة لأغراض مختلفة داخل OLLYDBG.


أود أن أضيف ، أعتقد أنه من العار أن مصادر Ollydbg غير متوفرة. لقد كنت تحت انطباع بأن disassembler المرتبط بشكل ثابت الذي يحتوي عليه كان تحت نوع من ترخيص GPL ، لكنني لم أحصل على أي حظ في الحصول على المصادر إلى Ollydbg.

نصائح أخرى

خذ رقم 32 بت من العنوان xxxxxxx ووضعه في سجل ECX ، ثم استخدم هذه القيمة كعنوان وقراءة القيمة ووضعها في سجل edx ، وأخيراً أضف 116 إلى هذا الرقم وقراءة قيمة هذا العنوان في EAX. ثم يبدأ تنفيذ الرمز في العنوان الذي تم عقده الآن في EAX. عندما يواجه هذا الرمز رمز الإرجاع ، سيستمر التنفيذ بعد تعليمات المكالمة.

هذا هو التجميع الأساسي جدا. يجعلني أتساءل WTF الذي تقوم به مع تصحيح الأخطاء وعندما تكون مهمتك مستحقة ؛-)

لقد كان الوقت لحظة منذ أن فعلت ASM (1997) وحتى ذلك الحين كنت أفعل فقط I386 ASM لذا سامحني إذا لم يكن إجابتي مفيدًا ...

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

على وجه التحديد ، يبدو أن البيانات أو ربما يتم تحميل مؤشر من هذا العنوان في سجل CX الخاص بك. ثم يتم نسخ هذه القيمة من CX إلى DX. لذلك لديك قيمة مؤشر CX الموجود في DX. ثم يتم نسخ هذه القيمة في DX بالإضافة إلى إزاحة 116 في سجل AX (المتراكم الخاص بك؟)

ثم مهما كانت الوظيفة الموجودة في هذا العنوان يتم نسخها في AX يتم تنفيذها.

أنا متأكد بنسبة 99 ٪ من أنها مكالمة افتراضية ، مع الأخذ في الاعتبار التعليقات حول كونه برنامج التحويل البرمجي MSVC.

MOV ECX,DWORD PTR DS:[xxxxxxxx]

يتم تحميل مؤشر إلى مثيل الفصل في ECX من متغير عالمي. (NB: الافتراضي __thiscall Calling Convention يستخدم ECX لتمرير مؤشر المثيل ، ويعرف أيضًا باسم هذه مؤشر).

MOV EDX,DWORD PTR DS:[ECX]

عادةً ما يكون مؤشر VFTable (جدول الوظائف الظاهرية) هو العنصر الأول في تخطيط الفئة. هنا يتم تحميل المؤشر في edx.

MOV EAX,DWORD PTR DS:[EDX+116]

يتم تحميل مؤشر الطريقة في الإزاحة 116 (0x74) في الجدول في EAX. نظرًا لأن كل مؤشر هو 4 بايت ، فهذه هي الطريقة الافتراضية الثلاثين للفئة (116/4 + 1).

CALL EAX

وتسمى الطريقة.

في C ++ الأصلي ، سيبدو شيء من هذا القبيل:

g_pObject1->method30();

لمعرفة المزيد حول تنفيذ MSVC لفئات C ++ ، بما في ذلك الأساليب الافتراضية ، راجع مقالتي هنا.

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