Reverse Code Engineering

逆向工程代码 обратная код машиностроения

Reverse Code Engineering

逆向工程代码 обратная код машиностроения

Reverse Code Engineering

Share what I know............... learn what I don’t

آخرین نظرات

سوییچ خیلی زیاد توسط برنامه نویس ها (مخصوصا بدافزارنویس ها) برای گرفتن تصمیم هایی مبتنی بر یک کاراکتر یا عدد استفاده می شود.

دستور سوییچ به دو صورت رایج کامپایل می شود: استفاده از استایل if یا جداول پرش.


If Style

کد مثال ما بسته به مقدار i یکی از موارد رو اجرا میکنه:


switch(i)

{

   case 1:

      printf("i = %d", i+1);

      break;

   case 2:

      printf("i = %d", i+2);

      break;

   case 3:

      printf("i = %d", i+3);

      break;

   default:

      break;

}

حالا کد دیس اسمبل این دستور بصورت زیر میباشد:

00401013        cmp     [ebp+var_8], 1

00401017        jz      short loc_401027 1(1)

00401019        cmp     [ebp+var_8], 2

0040101D        jz      short loc_40103D

0040101F        cmp     [ebp+var_8], 3

00401023        jz      short loc_401053

00401025        jmp     short loc_401067 2(2)

00401027 loc_401027:

00401027        mov     ecx, [ebp+var_4] 3(3)

0040102A        add     ecx, 1

0040102D        push    ecx

0040102E        push    offset unk_40C000 ; i = %d

00401033        call    printf

00401038        add     esp, 8

0040103B        jmp     short loc_401067

0040103D loc_40103D:

0040103D        mov     edx, [ebp+var_4] 4(4)

00401040        add     edx, 2

00401043        push    edx

00401044        push    offset unk_40C004 ; i = %d

00401049        call    printf

0040104E        add     esp, 8

00401051        jmp     short loc_401067

00401053 loc_401053:

00401053        mov     eax, [ebp+var_4] 5(5)

00401056        add     eax, 3

00401059        push    eax

0040105A        push    offset unk_40C008 ; i = %d

0040105F        call    printf

00401064        add     esp, 8


فک نکنم دیگه نیاز به توضیح خط به خط داشته باشه و بصورت کلی توضیح میدم.

بین شماره (1) و (2) یه سری دستور پرش شرطی وجود داره. اگه به دستور بالای هر پرش شرطی نگاه کنید میبینید که یه مقایسه انجام شده.بعنوان مثال خط اول متغیر i رو با عدد 1 مقایسه میکنه و اگه درست باشه پرش انجام میشه به دستورات case 1 .

خود شماره (2) که یه پرش غیر شرطی هستش نقش default رو بازی می کنه و چون دستوری داخل این وجود نداره پس یه پرش به خارج از دستور سوییچ انجام میشه, درست همین پرش بعد از اجرای هر دستور case هم انجام میشه.

 

تشخیص دستور سوییچ از زنجیره ای از دستورات if توی دیس اسمبلی مشکل هستش, اگر چه مهم نیستش, چون هدف اصلی در اینجا پی بردن به نحوه ی عملکرد این دستورات هستش نه رسیدن به سورس کد اصلی.

 

Jump Table 

حالا ما میایم یه case دیگه به سورس کد بالا اضافه می کنیم:


switch(i)
{
   case 1:
      printf("i = %d", i+1);
      break;
   case 2:
      printf("i = %d", i+2);
      break;
   case 3:
      printf("i = %d", i+3);
      break;
   case 4:
      printf("i = %d", i+3);
      break;
   default:
      break;
}

حالا کد دیس اسمبلی تولید شده این کد:

00401016        sub     ecx, 1

00401019        mov     [ebp+var_8], ecx

0040101C        cmp     [ebp+var_8], 3

00401020        ja      short loc_401082

00401022        mov     edx, [ebp+var_8]

00401025        jmp     ds:off_401088[edx*4] (1)

0040102C   loc_40102C:

              ...

00401040        jmp     short loc_401082

00401042   loc_401042:

              ...

00401056        jmp     short loc_401082

00401058   loc_401058:

              ...

0040106C        jmp     short loc_401082

0040106E   loc_40106E:

              ...

00401082   loc_401082:

00401082        xor     eax, eax

00401084        mov     esp, ebp

00401086        pop     ebp

00401087        retn

00401087   _main   endp

00401088  2off_401088  dd offset loc_40102C  (2)

0040108C               dd offset loc_401042

00401090               dd offset loc_401058

00401094               dd offset loc_40106E


بیشترین کارایی کد اسمبلی بالا در استفاده از جدول پرش (2) است که آفست هایی به مکانهای حافظه ی اضافی را تعریف می کند. 
متغیر سوییچ بعنوان اندیسی به داخل این جدول پرش استفاده شده است.
در این مثال ecx محتوی متغیر سوییچ است که یک واحد از آن در خط اول کاسته می شود.در کد زبان سی, جدول سوییچ رنج 1 تا 4 است و در کد اسمبلی این اندیس ها از 0 تا 3 تنظیم میشوند تا جدول پرش بدرستی اندیس گذاری شود.
دستور پرش (1) مسئول این جدول پرش است, که در اینجا edx در 4 ضرب شده و به مبنای جدول پرش (0x401088) اضافه میشود تا پرش به case مورد نظر مشخص شود.
دلیل این ضرب شدن هم این است که آدرسهای این جدول پرش هر کدام 4 بایت سایز دارند.

نظرات (۱)

رضا جان پاسخ به ایمیلت ارسال شد
pcrlth0n
ارسال نظر آزاد است، اما اگر قبلا در بیان ثبت نام کرده اید می توانید ابتدا وارد شوید.
شما میتوانید از این تگهای html استفاده کنید:
<b> یا <strong>، <em> یا <i>، <u>، <strike> یا <s>، <sup>، <sub>، <blockquote>، <code>، <pre>، <hr>، <br>، <p>، <a href="" title="">، <span style="">، <div align="">
تجدید کد امنیتی