לדלג לתוכן

מה זה קוד עצמאי מיקום - PIE

כשתוכנית רגילה נטענת לזיכרון, יש לה בדרך כלל כתובת קבועה שבה היא "יושבת" - כאילו יש לה כתובת בית מוכרת מראש. זה נוח, אבל זה גם בדיוק מה שהופך אותה למטרה קלה לתקיפה. קוד עצמאי מיקום, או Position Independent Code, פותר את הבעיה הזאת בדרך אלגנטית - הוא הופך את התוכנית לכזו שפשוט לא אכפת לה איפה היא נמצאת בזיכרון.

מה זה אומר שקוד "לא יודע" איפה הוא נטען

תוכנית רגילה, לא עצמאית מיקום, בנויה מתוך הנחה שהיא תיטען תמיד לאותה כתובת זיכרון קבועה. כל קפיצה בתוך הקוד, כל הפניה למשתנה גלובלי, יכולה להיות מקודדת ישירות ככתובת מוחלטת, כי הקומפיילר "יודע" מראש איפה הכל יהיה.

קוד עצמאי מיקום עובד אחרת לגמרי. הוא לא מניח שום דבר לגבי הכתובת שבה הוא ייטען. במקום זה, כל הפניה פנימית בתוך הקוד מנוסחת באופן יחסי - "קפוץ עשרים בתים קדימה ממני", ולא "קפוץ לכתובת המוחלטת הזאת". התוצאה היא שאותו קובץ בינארי בדיוק יכול להיטען לכתובת אחת בהרצה אחת, ולכתובת שונה לחלוטין בהרצה הבאה, בלי שהקוד עצמו יתקלקל או יצטרך להשתנות.

למה בכלל צריך את זה - ASLR

הסיבה המרכזית שבגללה כל זה חשוב היא מנגנון הגנה שנקרא ASLR, ראשי תיבות של Address Space Layout Randomization, כלומר אקראיות בפריסת מרחב הכתובות. הרעיון פשוט - בכל פעם שתוכנית רצה, מערכת ההפעלה טוענת אותה לכתובת אקראית שונה בזיכרון, במקום לכתובת קבועה.

למה זה חשוב מבחינת אבטחה? הרבה מתקפות ניצול חולשות מסתמכות על ידיעת כתובות מדויקות בזיכרון - למשל, כתובת של פונקציה מסוימת שהתוקף רוצה לקפוץ אליה, או כתובת של קוד זדוני שהוא הכניס לתוכנית. אם הכתובות תמיד קבועות, תוקף יכול פשוט לחשב אותן מראש ולהשתמש בהן. אבל אם כל הרצה מקבלת כתובות אקראיות, התוקף צריך פשוט לנחש, וניחוש נכון של כתובת מדויקת בטווח כתובות ענק הוא הרבה יותר קשה.

הבעיה היא ש-ASLR לא יכול לעבוד על תוכנית רגילה שמניחה כתובת קבועה - אם תזיזו אותה, כל ההפניות הפנימיות שלה יתקלקלו. בדיוק בשביל זה נדרש קוד עצמאי מיקום. הוא התשתית הטכנית שמאפשרת בכלל להזיז את התוכנית מבלי לשבור אותה.

איך זה מושג ברמה הטכנית

ברמה מושגית, ההבדל בין קוד רגיל לקוד עצמאי מיקום הוא ההבדל בין כתובות מוחלטות לכתובות יחסיות. במקום שהקומפיילר יכתוב "קפוץ לכתובת 0x400500", הוא כותב משהו שקרוב יותר ל"קפוץ למקום שנמצא בהיסט קבוע ממני עכשיו".

כדי לממש את זה בפועל, המעבד משתמש ברעיון של רגיסטר בסיס - רגיסטר שמחזיק את הכתובת שבה התוכנית בפועל נטענה בהרצה הנוכחית. כל הפניה בקוד מחושבת כהיסט מתוך הרגיסטר הזה, ולא ככתובת קבועה. כשמערכת ההפעלה טוענת את התוכנית לכתובת אקראית כלשהי, היא פשוט מציבה את הכתובת הזאת ברגיסטר הבסיס, וכל שאר הקוד ממשיך לעבוד נכון בלי לדעת ובלי לשים לב שהוא בכלל הוזז ממקום למקום.

זה גם ההבדל בין תוכנית רגילה שממופה לכתובת קבועה מראש, שנפוצה יותר בקבצי הפעלה ישנים או פשוטים, לבין תוכנית עצמאית מיקום, שהיא הסטנדרט כמעט בכל מקום היום.

למה כמעט כל תוכנית מודרנית מקומפלת ככה

היום, כמעט כל תוכנית שמקומפלת במערכות הפעלה מודרניות מקבלת אוטומטית את התכונה הזאת כברירת מחדל, בלי שהמפתח בכלל צריך לבקש את זה במפורש. זה קרה כי ההבנה באבטחת מידע התקדמה - פעם קוד עצמאי מיקום נחשב לתוספת שמורידה קצת ביצועים בגלל החישוב הנוסף של כתובות יחסיות, ולכן השתמשו בו בעיקר בספריות משותפות. אבל עם הזמן, המחיר בביצועים ירד משמעותית בזכות שיפורים בחומרה ובקומפיילרים, בזמן שהתועלת באבטחה נשארה גבוהה מאוד.

היום ההיגיון הפוך לגמרי - קומפיילרים כמו GCC בונים תוכניות כעצמאיות מיקום כברירת מחדל, ומי שרוצה תוכנית בלי ההגנה הזאת צריך לבקש את זה במפורש. זה שיקוף נאמן של איך שעולם האבטחה זז - מהגנות אופציונליות שאפשר להוסיף, להגנות בסיסיות שצריך מאמץ מודע כדי להסיר.

למה זה מעניין במיוחד למי שחוקר חולשות

מי שעוסק במחקר חולשות ובניצול תוכנות פוגש את קוד עצמאי המיקום כמעט בכל אתגר. כשמנתחים בינארי כדי למצוא דרך לנצל חולשה בו, אחת השאלות הראשונות היא אם הוא נקמפל כעצמאי מיקום או לא, כי זה קובע איזה אסטרטגיות ניצול בכלל אפשריות. בקורס ליבת המחשב אנחנו נכנסים לעומק לנושאים כאלה, כי הבנה של הגנות ברמת המערכת היא בדיוק מה שמבדיל בין מי שרק מכיר את המושגים לבין מי שיודע להשתמש בהם בפועל.

לסיכום

קוד עצמאי מיקום הוא דוגמה יפה לאיך שפתרון טכני נקודתי - הפיכת כתובות מוחלטות ליחסיות - הפך להיות אבן יסוד בהגנת אבטחה שלמה שכל תוכנה מודרנית נהנית ממנה. בלי היכולת הזאת, ASLR פשוט לא היה יכול להתקיים, והתקפות שמסתמכות על כתובות קבועות היו הרבה יותר קלות לביצוע.

מוזמנים לבוא לדיסקורד ולדבר על זה יותר לעומק, במיוחד אם אתם מתעסקים עם ניתוח בינאריים ורוצים להבין איך זה נראה בפועל.

הצטרפו לקהילה בדיסקורד