تساعد في فك تشفير بضعة أسطر من التجميع
سؤال
لقد وجدت هذه الأسطر القليلة من التجميع في 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 مختلفًا struct
S التي تحتوي على بعض مؤشرات الوظائف. هناك أيضًا صفائف من مؤشرات الوظائف ، ولكن التوجيه المزدوج للوصول إلى 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 ++ ، بما في ذلك الأساليب الافتراضية ، راجع مقالتي هنا.