היי חברים
הרבה זמן לא כתבתי פה, ואין לי הרבה זמן כרגע,
אבל גיליתי משהו נחמד שרציתי לחלוק אתכם. אין לי כוח למצוא את הסיסמה
לבלוג הישן שהתחלתי לכתוב בנושאים הטכניים האלה, אז אני פשוט אכתוב כאן קוד פולימורפי, מויקיפידיה, למי שלא מכיר:
"בעולם התוכנה ואבטחת המידע, קוד פולימורפי הוא סוג של תוכנה זדונית (Maleware),
כדוגמת וירוס, שעוברת מוטציה בכל הדבקה, ובכך מקשה על
תוכנות אנטי וירוס המבוססות על קובץ חתימות לזהותה."
אני לא לגמרי מסכים עם ההגדרה בויקיפדיה, כי קוד פולימורפי הוא לא בהכרח Malware. גם Google Desktop מצפינים את הקוד שלהם, והתוכנה שלהם היא בטח לא Malware
אבל הרעיון הוא, שאפשר לכתוב קוד שיראה מוצפן כאשר ינסו לבצע לו Reverse Engineering - אך הקוד יעבוד היטב מכיוון שהוא יעבור פענוח on demand
כלומר, בכל כניסה לפונקציה יהיה איזשהו prologue שיפענח את הפונקציה, ובסיומה יהיה epilogue שיצפין אותה חזרה.
המימוש, כמובן, הרבה פחות טריוויאלי - צריך להתחשב בענייני thread safety ותאימות למערכות הפעלה שונות,
אבל לא על זה מדבר הפוסט שלי - על הנושאים האלה יש מידע באינטרנט בשפע.
נניח שלדוגמה יש את הקוד הפשוט הבא:
void test() { size_t size = 0; byte* thisFunc = encryptDecrypt(size); printf("Test-> Now on printf, successfully printed!\n"); FUNCTION_EPILOG(); encryptDecryptEx(thisFunc, size); }
|
לצורך הפשטות - FUNCTION_EPILOG הוא מאקרו שמגדיר 5 פעמים את האופקוד nop, על מנת לזהות את סוף הפונקציה לצרכי ההצפנה:
#define FUNCTION_EPILOG() { _asm nop \ _asm nop \ _asm nop \ _asm nop \ _asm nop }
|
פונקציות ההצפנה(אם אפשר לקרוא לזה ככה, לצורך הפשטות, xor ff):
byte* encryptDecrypt(size_t &size) { byte* codeToEncrypt; __asm { push eax mov eax, [ebp]+4 mov [codeToEncrypt], eax pop eax } size = .. ; /* find size by locating the 5 nops */ encryptDecryptEx(codeToEncrypt, size); return codeToEncrypt; } void encryptDecryptEx(byte* code, size_t size) { byte* ptr = code; DWORD old = 0; VirtualProtect((LPVOID)ptr, size, PAGE_EXECUTE_READWRITE, &old) == 0; /* should, of course, check the return value of VirtualProtect and stuff... */ for (size_t i = 0; i < size; ++i) { *ptr ^= 0xFF; ptr++; } }
|
*נקודה קטנה, הקוד נורא מכוער ולא רציני, זה כמובן כי אין לי כוח לכתוב עכשיו קוד רציני למטרת פוסט
עכשיו - הדבר המעניין.
אם תנסו להריץ את הקוד הנ"ל עם גודל קטן, נניח של 4 בתים(שאותם תקסרו ff מראש, באמצעות hex workshop או כל תוכנה דומה) סביר שהכל יעבוד... אבל מה יקרה אם תנסו עם גודל גדול יותר?
אופס! לא עובד.
אחרי בדיקה סיזיפית של גדלים, בנסיון להבין את הבעיה, הגעתי למסקנה(שנבדקה אחר כך ואושרה כנכונה) שהבעיה היא ה- ASLR!
מהו ASLR? Address space layout randomization (ASLR) is a computer security technique which involves randomly arranging the positions of key data areas, usually including the base of the executable and position of libraries, heap, and stack, in a process's address space.
ב- Windows 7 יש מנגנון שנועד בעיקרו למנוע ניצול של חולשות Buffer
Overflow, שבעת הפעלה של קובץ PE(exe, dll) מערכת ההפעלה משנה את ה
Base Address של הקובץ, ובהתאם, משנה את כתובות כל הפונקציות בתוכנית.
מסתבר, שבעת הפעלת התוכנית הפולימורפית שלנו, מערכת ההפעלה משנה את כל
הכתובות, אך אם יש לנו קפיצות לכתובות או שימוש בפונקציות בקטע הקוד
שהוצפן, מערכת ההפעלה לא יכולה לדעת את זה ולכן לא משנה את הכתובות שם.
כאשר נפענח את הקובץ, יהיו שם קפיצות ושימוש בכתובות זכרון ישנות, לפני השינוי - ולכן התוכנית לעולם לא תעבוד.
אותה התוכנית בדיוק תעבוד על Windows XP לדוגמה...
זהו סתם נקודה מעניינת שיצא לי לראות, וחשבתי שיהיה נחמד לשתף.
יום טוב
\x6C\x65\x65\x74\x68\x61\x78\x30
\x72\x3A\x2D\x29
tresp4sser