یعنی از نتیجه برگردید به عقب
تا اینجا در Data Flow Analysis یاد گرفتیم داده از کجا وارد میشه و چه مسیری رو طی میکنه
Backward Slicing
دقیقا برعکسشه
اینجا از یک نقطه مهم شروع میکنیم و برمیگردیم عقب تا بفهمیم چه چیزهایی باعث به وجود اومدن اون نتیجه شدن
مثلا فرض کنید این کد رو داریم:
C++
int process(int a, int b)
{
int x = a + b;
int y = x * 2;
int junk = 500;
junk ^= 123;
return y;
}
اگر هدفمون
return y باشه از y شروع میکنیممیپرسیم:
yاز کجا اومده?
جواب:
y = x * 2
پس حالا باید بفهمیم
x از کجا اومدهx = a + b
پس
a و b روی خروجی تاثیر دارنحالا اگر به
junk نگاه کنیم میبینیم هیچ مسیری به y یا خروجی ندارهپس در این تحلیل میتونیم فعلا کامل نادیدهاش بگیریم
مسیر Backward Slice این شکلیه:
Return y
↑
y = x * 2
↑
x = a + b
↑ ↑
a b
این روش مخصوصا وقتی با یک تابع خیلی بزرگ و شلوغ طرفید فوقالعاده کاربردیه
چون لازم نیست از اول تابع تا آخرش همه چیز رو تحلیل کنید اول مشخص میکنید دنبال چی هستید
مثلا:
نتیجه یک شرط
مقدار خروجی
یک آدرس مهم
یک مقدار نوشتهشده در حافظه
یا یک تابع مهم
بعد از همون نقطه شروع میکنید و به عقب برمیگردید
فرض کنید داخل دیساسمبل این رو میبینید:
cmp eax, 1
jne failed
سوال مهم این نیست که فقط
jne کجا میرهاول باید بپرسید:
مقدار
EAX قبل از این مقایسه از کجا اومده؟ممکنه چند دستور قبل:
call check_value
وجود داشته باشه
حالا باید برگردید و ببینید
check_value چی برمیگردونهیا شاید
EAX از یک محاسبه طولانی اومده باشهدر این حالت Backward Slicing کمک میکنه فقط دستورهایی رو بررسی کنید که واقعا روی مقدار نهایی
EAX تأثیر دارناین کار توی برنامههای Obfuscate شده خیلی مهمه چون ممکنه دور یک شرط مهم صد تا دستور اضافی وجود داشته باشه
اما شاید فقط ده دستور واقعا روی نتیجه اون شرط تاثیر بذارن هدف Backward Slicing دقیقا پیدا کردن همین دستوره
یک نکته مهم اینه که باید فقط دنبال وابستگی مستقیم نباشید
مثلا:
A
روی B تاثیر میذاره
B
روی C
C روی نتیجه
پس
A هم بخشی از Slice محسوب میشه حتی اگر مستقیم به نتیجه وصل نباشهتمرین:
این تابع رو بررسی کنید:
C
int verify(int input)
{
int a = input * 2;
int b = a + 15;
int temp = 100;
temp += 50;
int result = b ^ 0x33;
return result;
}
از
return result شروع کنید و به عقب برگردید مشخص کنید کدوم متغیر ها واقعا روی خروجی تاثیر دارنبعد مسیرش رو روی کاغذ رسم کنید
input
↓
a
↓
b
↓
result
↓
return
temp رو هم بررسی کنید میبینید که وجود داره و چند عملیات روش انجام میشه ولی هیچ اثری روی خروجی نداره و دقیقا همینجاست که Backward Slicing به ما کمک میکنه وسط تعداد زیاد کد از کد مستقیم بریم سراغ چیزی که واقعا مهمه
@reverseengine