435
2

מסבירים מהם Rootkits: דוגמאות פרקטיות, דרכי חקירה ומבט אל מאחורי הקלעים

435
זמן קריאה: 10 דקות

Rootkits – מי הם בעצם?

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

  1. User-Space Rootkits
  2. Kernel Space Rootkits

השם דיי אינדיקטיבי, אך נאמר זאת בכל אופן – סוג אחד פועל במרחב ה – User Space, בו רצות כל התוכניות בהם המשתמש משתמש (ותכניות נוספות כגון דרייברים ספציפיים וכ’ו..).
התוכניות הרצות במרחב זה ירוצו בהרשאות המינימליות הדרושות לריצה התקינה שלהן.
סוג אחר פועל במרחב ה – Kernel Space, בו רצות תכניות הליבה של מערכת ההפעלה.
הן אחראיות על ניהול התוכניות הרצות ב – User Space מבחינת משאבי זיכרון, מניעת collisions וכ’ו…
תכניות במרחב זה מאופיינות בריצה בהרשאות גבוהות!

אזור ה – Kernel Space מיועד להיות אזור מבודד ותוכניות ב – User Space ניגשות אליו בצורה מבוקרת דרך קריאות מערכת הקרויות System Calls, הבאות: SYSCALL, SYSENTER, INT 0x2E.
*לא ניתן לגשת ישירות מה – User Space אל ה – Kernel Space, לכן בפועל נעשה שימוש ב – lookup tables בכדי לזהות לאיזה פונקציה ב – Kernel עלינו לקרוא…לא ניכנס לזה כאן 😄

**בגלל שתוכניות הרצות ב – Kernel ירוצו בהרשאות חזקות, לרוב נראה בקרב Rootkit-ים פונקציונאליות יותר מורכבות (וקשות לניתוח) כמו: הסתרת קבצים, הסתרת Process-ים הרצים במערכת, הסתרת חיבורי Network Connections ונוספים…
With That Being Said – כתיבת Malware שרץ ב – Kernel הרבה יותר מורכבת עקב העובדה שהכתיבה מתבצעת ב – Kernel, יש הרבה פחות פונקציות מוכנות ונתמכות (Pre-Made) – בקיצור כאב ראש לא קטן…לכן רק Malware-ים מורכבים יכילו Kernel Component מסוג כזה או אחר.

דוגמאות ל – Rootkit-ים – הלכה למעשה

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

Rootkit ראשון
צילום המסך מציג Snapshot בו ה – Rootkit כבר רץ אך בפעול, לאחר מעבר על ה – Process-ים ב – Process Explorer, אין כלל עדות לכך שהוא רץ בפועל.
לאחר ניתוח ב – IDA Pro, אנחנו אכן רואים שמתבצעות קריאות ליצירת Service – מה שמעלה את החשד שקיים Kernel Component שמעורב ברקע ושאכן מדובר ב – Rootkit.

Rootkit שני
צילום המסך הזה מציג Snapshot בו ה – Rootkit כבר רץ בפועל, אנחנו רואים שאכן יש עדות שנוצר הקובץ Mlwx486.sys בתיעוד של Process Monitor וזה תואם את קוד ה – Assembly שאנחנו רואים ב – IDA Pro…עם זאת, כשאנחנו מנסים לגשת לתיקייה במטרה להמשיך לחקור את הקובץ שנוצר – הוא לא נמצא שם.

Rootkit שלישי
אחרון חביב, Rootkit שכבר רץ בעמדה.
בהתבסס על קוד ה – Assembly ב – IDA Pro, (שאגב רץ בדרייבר נפרד כקובץ sys.), נראה שאכן מתבצעת כתיבה ושינוי ה – Registry.

**את הדרייבר הנוסף היינו צריכים למצוא על מנת לאפשר ריצה תקינה של קובץ ה – exe המקורי.
מציאת הקבצים הזדוניים בעמדה שנתקפה הוא עולם ומלואו הקרוי – Digital Forensics & Incident Response (או DFIR בקיצור) – מאמין שאסקור נקודות מפתח בהקשר לתחום הזה באחת הכתבות הבאות🧐

עם זאת, ב – Process Explorer אין אף עדות לכך שהקובץ רץ כרגע ו- העדות היחידה לכתיבה ל – Registry שניתן לראות ב – Process Monitor היא ערך Seed גנרי שמשתנה לעיתים תכופות.

*כהערת אגב, ב – Malware-ים המממשים פונקציונאליות הקשורה ל – Kernel לרוב נראה את הדברים הבאים:

  1. שימוש בפונקציות עם התחילית Rtl, למשל: RtlWriteRegisrty, RtlCreateRegistryKey.
  2. שימוש בקובץ ה – exe הבא: ntoskrnl.exe, המכיל פונקציות שנמצאות ב – Kernel Space.

*קיימות פונקציות Kernel (עם תחילית Rtl, למשל RtlUnwind) שקיימות בכל קובץ exe ולכן לא ניחפז לקבוע שכל קובץ exe המכיל פונקציית Rtl מממש Kernel Component או בכלל מוגדר כקובץ זדוני.

Kernel Debugging ו – Device Objects

לפני שנציג את עיקר הניתוח של כל Rootkit, נקדיש רגע להבין איך בפועל נרצה לנתח Malware-ים המכילים רכיב Kernel כזה או אחר.
כמו שצוין קודם, תכניות/אפליקציות לא מתקשרות ישירות עם ה – Kernel.
Windows כן מאפשרת לתכניות/אפליקציות להריץ קוד ב – Kernel של Windows.
תכניות/אפליקציות לא יכולות לגשת ישירות ל – Kernel Drivers אלא עושות זאת דרך Device Objects שמעבירות הלאה את הבקשות ל – Device-ים ספציפיים.
Device-ים לא בהכרח יהיו התקנים חומרה פיזיים.
Device-ים נוצרים ונמחקים אליהם ניתן לגשת דרך ה – User Space.
לדוגמא, כשאנחנו מכניסים USB Flash ל – PC שלנו, Windows יוצר Device Object עבור ה – Drive שנוצר. כעת אפליקציות ב – User Space יכולות לגשת לדרייבר המשויך אליו, והוא בתורו יגש ל – Driver שאחראי לטיפול בהתקני USB.
אותו דרייבר אחראי, מטפל בבקשות גישה ל – USB Flash נוסף (פוטנציאלית) אבל תכניות/אפליקציות יגשו אליו דרך Device Object אחר.

Debugging של ה – Kernel הוא יותר מורכב מאשר ביצוע Debugging לתכניות שרצות ב – User-Space.
כשיש Breakpoint ב – Kernel (והוא נמצא במצב של Debug) כל מערכת ההפעלה “קופאת”, שכן אם ה – Kernel ב – Breakpoint, מי יריץ את מערכת ההפעלה right?
לכן, לרוב נבצע Kernel Debugging במכונה וירטואלית (VM) שמאופשר בה ביצוע Debugging (מצריך שינוי הגדרות ו- setup ראשוני, לא נכנס לזה כאן…).
את ה – Kernel Debugging נבצע בעזרת WinDbg ב – Guest OS לצורך ביצוע Breakpoint-ים והמשך ריצה של ה – Malware, וב – WinDbg Preview ב – Host OS (צריך הרי לבצע Debug על כל ה – Kernel של ה – Guest OS ולכן נצטרך גם מכונה חיצונית – בה גם ירוץ כלי לביצוע Kernel Debugging).

ניתוח תמציתי של כל Rootkit – מאחורי הקלעים

לא נציג כאן ניתוח מלא של כל Malware Sample אלא רק את תהליך העבודה עם WinDbg Preview וזיהוי מימוש ה – Rootkit ב – Kernel Space.

ניתוח – Rootkit ראשון

  1. ראינו ב – IDA Pro כי נוצר Service בשם “Process Helper” שמצביע לדרייבר כלשהו בזיכרון:
    Lab10-03.sys.
  2. אם ננבור עוד קצת בקוד ה – Assembly נגלה כי מתבצעת קריאה לפונקציה: DeviceIoControl הנקראת בעת ביצוע request של module ב – User – Space ל – Object Device המנוהל ע”י driver.
    נוכל לשער (על סמך מחקר מקדים ב – IDA וקצת ניסיון) כי ייווצר Device Object ע”י ה – Kernel Driver ב – ProcHelper\.\ שיאפשר תקשורת בין ה – User Space Component ל – Kernel Driver Component.
  3. כעת, יש לנו kernel module שנרצה לחקור אז נעבור ל – WinDbg Preview ונחפש אחר ה – device object הבא: ‘ProHelper’ עם הפקודה: devobj ProcHelper!

4. משמצאנו את הכתובת בה הוא שמור בזיכרון, נחפש מידע נוסף אודות ה – device object בכתובת.
נשתמש בפקודה: dt nt!_Driver_OBJECT 86550220

5. נמשיך לדלות מידע אודות הפונקציות אותן הדרייבר מממש (MajorFunction) בעזרת הפקודה:
dd 86550220+0x38
*dd – קורא מהזיכרון ומציג כ – 32 bit בתור double value.

6. רוב הכתובות מקבלות ערכים גנריים (הכתובות התחתונות לא רלוונטיות) פרט ל-3 כתובות שאלו הפונקציות שה – Malware מממש.
7. נמשיך לחקור כל אחת מהכתובות האלו בעזרת dump pointer symbols, עם הפקודה:
dps 86550220+0x38
ונגלה מידע נוסף אודות הכתובות הללו בזיכרון.
הן מתויגות כך: Lab10 03 + 0x606 ו- Lab10 03 + 0x666.
8. כעת, נוכל לבצע decompile ל – Malware, ומפונקציית ה – start לקפוץ ל – Offset-ים שמצאנו.
כעת נוכל ממש לנתח מה כל פונקציה מבצעת.

אם נמשיך בניתוח, נגלה כי בעצם מתבצע Unlinking ל – Process הנוכחי שרץ (הזדוני) ע”י שינוי המצביעים ברשימה המקושרת הדו כיוונית של כל ה – Process-ים שטעונים בזיכרון (ובעצם מצביעים אחד לשני).
זה מתבצע על שינוי של שדות ה – FLINK וה – BLINK של ה – EPROCESS Structure של ה – Process שלפני ה – Process הזדוני שיצביע לזה שאחריו, ושינוי המצביע של ה – Process שאחרי ה – Process הזדוני שיצביע לזה שלפניו (לפני ה – Process הזדוני).
וזו בעצם הסיבה, למה לא ראינו את ה – Process הזדוני ב – Process Explorer בעת הניתוח הראשוני.

*שינוי המצביעים בעצם נעשה בעזרת גישות ל – [eax], [eax+4], [ecx] ו – [ecx+4] בדומה לגישות שהיו מתבצעות אם היינו כותבים את הקוד הזה בשפה עילית כלשהי.
שם זה היה נראה בדומה כך: node.next(), node.prev בהתאם ל – Process המתאים.

הערה נוספת – בגדול כל Process מיוצג בזיכרון ע”י EPROCESS Structure.
ה – Structure הזה הוא בלוק בזיכרון או במינוח יותר נכון – Kernel Object שקיים לכל Process שמכיל Attributes שאפיינות את ה – Process הזה…ביניהם גם המצביעים Flink שמצביע ל – Process הבא ו- Blink שמצביע ל – Process הקודם (ה – Structure-ים האלו בזיכרון מצביעים אחד לשני ב – LinkedList Like Manner).

ניתוח – Rootkit שני

  1. אם נמשיך לחקור קצת ב – IDA Pro נגלה כי ה – Malware יוצר Service עם driver שלא ניתן לראות במערכת הקבצים עצמה (אך כן יש לו זכר ב – IDA Pro) העונה על השם: WS Driver 486.
  2. נוודא שה – Service שה – Malware יוצר עדיין רץ (כלומר הקוד ב – Kernel עדיין רץ), נריץ ב – Guest OS את הפקודה – sc query “486 WS Driver

3. ה – Service אכן עדיין רץ וה – Kernel Driver עדיין בזיכרון, נמשיך לחקור את ה – driver הזה בזיכרון ה – Kernel.
נסקור את כל ה – module שטעונים בזיכרון ה – Kernel בעזרת הפקודה lm:

4. נלחץ על ה – driver (מה שיגרום להרצת הפקודה: lmDvmMlwx486, מה שיתן לנו מידע נוסף על ה – module הזה בזיכרון (הכתובת בו הוא מתחיל ומסתיים בזיכרון ועוד…)

5. כיוון שמדובר בקובץ שלא מופיע במערכת הקבצים שלנו, ייתכן כי מדובר ב – SSDT Hooking.
בקצרה, מתבצע Hooking לכתובת כלשהי בזיכרון ה – Kernel כך שתיקרא פונקציה זדונית במקום הפונקציה שאמורה להיקרא.
נבצע dump pointer symbols לערכים ב – SSDT (נבחר להציג – 100 ערכים), כלומר לפונקציות שנטענו ל – Kernel, עם הפקודה הבאה: dps KiServiceTable L100:

בתרחיש נורמטיבי, כל הפונקציות היו שייכות לאותו module והוא ntoskrnl.exe ויצביעו לאותו טווח כתובות בזיכרון…האנומליה לגמרי בולטת לעין במקרה הזה.

6. אכן התבצע Hooking לאחת הרשומות ב – SSDT על מנת להריץ פונקציה של הפוגען.
7. כעת נחזור ל – IDA Pro ונראה מה קורה בכתובת המתאימה עם ה – Offset הבא: 0x486 ונגלה כי הפונקציה עליה מתבצע ה – Hooking היא NtQueryDirectoryFile.

8. אם נמשיך לחקור נגלה כי ה – hook יקרא לפונקציית ה – Windows API הלגיטימית במידה מדובר בכל קובץ ששמו לא מתחיל ב – Mlwx, אחרת תתבצע קריאה לפונקציה של הפוגען שתגרום למחיקת הקובץ.

ניתוח – Rootkit שלישי

אחרי שזיהינו כי מתבצעת קריאה לפונקציה ControlService ב – User Space, נרצה לדעת מה מתרחש ב – Kernel Space בעקבות הקריאה הזו.

  1. נגדיר Breakpoint ב – VM שלנו בכתובת בה מתבצעת הקריאה לפונקציה זו, באופן הבא:
    bp 0x00401080
  2. ניתן ל – Guest OS לרוץ (נקליד ‘g’) וכעת ניזום Break ב – Host OS.
  3. נריץ ב – Host OS את הפקודה: drvobj lab10-01! לצורך איתור הדרייבר שאנחנו חוקרים במטרה לראות אם יש device objects המתממשקים איתו מה – User Space.
  4. ניווכח לדעת כי הדרייבר נטען לכתובת: 0x86629d00 ושהוא לא מתממשק עם אף Device Object מה – User Space.

5. כעת כשיש לנו את הכתובת אליה הוא נטען, ננסה למצוא מידע נוסף אודות הדרייבר בעזרת:
dt_DRIVER_OBJECT_86629d00

6. נרצה לדעת מה קרה לפני שהדרייבר מופה החוצה מהזיכרון ולכן נגדיר Breakpoint נוסף בכתובת 0xf7f2e486.
7. ניתן ל – Guest OS לרוץ, נחכה שה – Breakpoint שהגדרנו יעצור את הריצה (ב – Host OS) ונראה שהריצה עצרה בכתובת הבאה בזיכרון:

נריץ עוד מספר פקודות בעזרת Step Into ונראה כי אכן מתבצעת גישה מרובה ל – Registry כמו שחשדנו שמתרחש:

המשך החקירה מכאן יהיה לחזור ל – IDA Pro לכתובות שאנחנו רואים כאן, בהן מתבצעות קריאות ל – RtlCreateRegistryKey לצורך קבלת תמונה מלאה יותר.
אם נעשה זאת, נראה כי ה – Malware משנה ערכים ב – Registry (מ-‘1’ ל-‘0’) לצורך ביצוע Disable ל – Firewall.


אז תכלס מה ראינו

  1. סקרנו קצת מה הם Rootkits, מה מאפיין אותם ובאיזה מרחב זיכרון הם פועלים לרוב.
  2. הרחבנו בקצרה אודות Kernel Space ו- User Space…יצא לנו גם לדבר על אופן הפעולה של Windows בהקשר ל – Driver-ים ו- Device Objects.
  3. ראינו מימושים מעשיים ל – 3 Rootkit-ים שונים וכיצד הם נראים בעיני המשתמש בעמדת הקצה.
  4. הסברנו קצת על איך נרצה לבצע Kernel Debugging וראינו כלים נפוצים לביצועו, כמו: WinDbg ו- WinDbg Preview.
  5. הצגנו ניתוחים ממקודים של רכיב ה – Rootkit בכל Malware Sample שראינו קודם.
    ראינו פקודות שונות לשימוש ב – WinDbg וכיצד היינו מנתחים את זיכרון ה – Kernel בעזרתן.
  6. באופן כללי, ראינו את קו המחשבה שנרצה ליישם בעת חקירת Rootkit-ים ו – Kernel Debugging.
  7. בתור תוספת קטנה, ראינו בקצרה איך Windows מתנהל בהקשר ל – Process-ים השונים שלו, ה – EPROCESS Structure ודרך בה Malware מנצל את המבנה שלהם (Double Linked List בה כל Process מצביע לזה שלפניו וזה שאחריו) לטובתו.

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

דן דורפמן
WRITEN BY

דן דורפמן

סטודנט למדעי המחשב באוניברסיטה הפתוחה.
SecOps Engineer & Automation Developer.
בעל תשוקה לתחום ה- Malware Analysis & Reverse Engineering.
בזמני הפנוי אני: לומד דברים חדשים, משחק כדורסל, שומע מוזיקה, ומדבר על החיים עם החבר'ה ;)

2 thoughts on “מסבירים מהם Rootkits: דוגמאות פרקטיות, דרכי חקירה ומבט אל מאחורי הקלעים

  1. היי דן,

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

    • · 8 במאי 2023 at 23:55

      שמח לשמוע שנהנת לקרוא יאנה.
      זה תלוי לאיזה מסלול את בוחרת לקחת את זה.
      אם את מכוונת יותר לפיתוח low level, אני פחות מכיר מקורות.
      יש המון קורסים בנושא של פיתוח ב – C++ – למרות שמהניסיון האישי שלי – לימוד מספרים נתן לי יותר ערך.

      אם הכוונה דווקא לתחום של Reverse Engineering & Malware Analysis, המקורות הבאים הם מקורות מעולים להתחיל בהם:
      ספרים:
      1. Practical Malware Analysis
      2. Reversing – Secrets of Reverse Engineering
      3. Practical Reverse Engineering
      קורסים:
      1. Zero to Automate
      2. SANS FOR610 (קורס יקר, לא לקחתי אותו, אבל שמעתי עליו לא מעט ביקורות טובות)

      מקור מעולה לתרגול – Reverse Engineering:
      https://challenges.re/?fbclid=IwAR1FuQOTj7AXRo2ESL8PLUiJzMLil9P9_AqH63BuoeJAcpcULieOMPopANg#Should%20I%20give%20low-level%20answer%20(what%20each%20instruction%20does)%20or%20high-level%20(what%20the%20function%20does)

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

כתיבת תגובה

האימייל לא יוצג באתר. שדות החובה מסומנים *