PracticU

פריצה של UnCrackable-Level3

בלי כתוביותעם כתוביות
PracticU › קורס סייבר והאקינג ל-Android - פריצה לטלפונים ואפליקציות אנדרואיד - בודק חוסן - Mobile App Pentesting › פריצה של UnCrackable-Level3
מילון מושגים:
ספרייה - אוסף קוד מוכן, כמו פונקציות ומחלקות, שמפתחים משתמשים בו בתוכניותיהם במקום לכתוב הכול מחדש.
הוק - נקודת חיבור שמאפשרת להריץ קוד מותאם בשלב מסוים של תהליך. ב-React, מנגנון לניהול מצב ויכולות ברכיבים.
פענוח - המרת מידע מוצפן חזרה לצורתו הקריאה בעזרת המפתח המתאים.
דיבאג - תהליך של איתור, הבנה ותיקון תקלות בקוד, לעיתים בעזרת כלי שמאפשר לעצור ולעקוב אחר ריצת התוכנית.
ASCII - תקן לקידוד תווים שמייצג אותיות, ספרות וסימנים כמספרים, ומשמש בסיס לייצוג טקסט במחשב.
תחביר - אוסף הכללים של שפת תכנות הקובעים כיצד לכתוב קוד תקין. הפרתם גורמת לשגיאת תחביר.
הצפנה - המרת מידע לצורה בלתי קריאה בעזרת מפתח, כך שרק מי שמחזיק במפתח המתאים יכול לפענח ולקרוא אותו.
ביט - יחידת המידע הקטנה ביותר במחשב, שערכה 0 או 1. שמונה ביטים מרכיבים בייט.

פריצה של UnCrackable-Level3
בשיעור זה אנו משלימים את הפריצה של האתגר השלישי: אנו מגלים את המחרוזת הסודית שמאותחלת בתוך פונקציה פנימית בספרייה, מציבים עליה הוק בעזרת כתובת והיסט, קוראים את ערכה ביציאה מהפונקציה, ובונים פונקציית פענוח שמבצעת פעולת XOR בין המחרוזת לבין המפתח הסודי ומגלה את התשובה הנכונה של האפליקציה.
נושאי הסיכום המוצגים בשיעור:
1. המטרה: אנחנו רוצים לגלות את המחרוזת הסודית. ניתחנו את הפונקציה שמשווה האם התוצאה שהמשתמש הקליד נכונה, והגענו למסקנה שהסוד הגדול נשמר בתוך הפונקציה שמאתחלת את המשתנה הסודי.
2. למה התפיסה ביציאה אינה מספיקה: אחרי שנתפוס את המשתנה ביציאה זה לא מספיק, כי צריך לקחת אותו ולעשות עליו פעולת XOR עם המפתח הסודי, ורק אחרי ה-XOR נדע את התשובה הנכונה, שהיא זו שמושווית לקלט המשתמש.
3. המפתח ידוע: אנחנו יודעים שהמפתח מאותחל בג'אווה, ראינו שהוא המילה פיצה כמה פעמים ברצף. השאלה הפתוחה היא מהי המחרוזת הסודית עצמה, ויש פונקציה שמאתחלת אותה, שאליה ניכנס.
4. הפרמטר הוא כתובת זיכרון: הפרמטר הראשון שמועבר לפונקציה הוא בעצם המחרוזת הסודית, כלומר האזור בזיכרון שלה. משנים את שם המשתנה לשם משמעותי שמציין שמדובר בכתובת הזיכרון של המחרוזת הסודית.
5. קריאת גוף הפונקציה: בפונקציה מתבצעות המון פעולות שקשה להבין במבט ראשון, ורק בסופה מתברר שהיא לוקחת את התוצאה, מכניסה את הכתובת ההתחלתית, מבצעת פעולות שונות ומחזירה תוצאה. אבל כשמסתכלים טוב על הקוד, מגלים שהקוד אינו משתמש במה שהפונקציה מחזירה, אלא במחרוזת הסודית עצמה, ולכן מה שחשוב לנו הוא ערכה של המחרוזת ביציאה מהפונקציה.
6. פונקציה פנימית בלי שם: אחרי סנכרון החלונות והצגת הקוד בצורה נוחה, מה שרצינו כל הזמן לגלות הוא הכתובת שבה הפונקציה מתחילה, כי אנחנו צריכים להתחבר אליה ואין לה שם. אין לה שם כי היא אינה מופיעה ברשימת הייצוא, היא פונקציה פנימית, ואפשר לזהות אותה רק לפי מספר הכתובת. השם שמוצג לה הוא שם שהמרצה המציא, כמו שעשה עם פונקציית האנטי דיבאג.
7. חישוב הכתובת האמיתית: הכתובת היחסית של הפונקציה ידועה. כמו שעשינו עם פונקציית האנטי דיבאג, לוקחים את כתובת הבסיס שבה המודול נטען לזיכרון ומוסיפים לה את ההזזה, ומקבלים את הכתובת האמיתית של הפונקציה שמאתחלת את המחרוזת הסודית.
8. Attach ולא Replace: הפעם לא רוצים להחליף את הפונקציה אלא להתחבר אליה, ולכן משתמשים ב-Interceptor Attach כמו שעשינו בהרצאות קודמות, ומתחברים לכתובת שחושבה. בכניסה תופסים את הארגומנט הראשון, שבו יושבת כתובת הזיכרון של המחרוזת הסודית, ושומרים אותו במשתנה משלנו, כי שם נמצא הסוד הגדול.
9. קריאת הערך ביציאה: אחרי שתפסנו את הכתובת בכניסה, ביציאה מהפונקציה אפשר להציץ פנימה: מבצעים קריאת זיכרון של 24 בתים מהכתובת ששמרנו, ושם יושב הסוד הגדול. זה הרגע שבו פונקציית האתחול מסתיימת וחוזרת אל הקוד הראשי, ואז למחרוזת יש את התוכן המלא שלה, כי היא עברה בכניסה, הפונקציה הוסיפה לה מידע ואחר כך התוכנה משתמשת בה.
10. הצורך בהיקף אובייקט: את הכתובת שמתקבלת בכניסה שומרים על המשתנה של האובייקט עצמו ולא בתוך פונקציית הכניסה, כדי שהוא יהיה זמין גם בפונקציית היציאה. אחרת ערך מקומי של פונקציה אחת אינו זמין לפונקציה אחרת, ואנחנו צריכים לקרוא את הזיכרון דווקא ביציאה.
11. הדפסת זיכרון: אפשר גם להדפיס תוכן זיכרון ישירות. הדפסה רגילה של כתובת זיכרון לא עובדת, כי צריך להדפיס אותה בצורה הקסדצימלית, ולשם כך קיימת פונקציית הצגת זיכרון שמקבלת מה להדפיס וכמה בתים, ומנסה גם לתרגם את הבתים לתווים לפי טבלת ה-ASCII.
12. תיקון שגיאות תחביר: בהרצה הראשונה מתקבלת שגיאה בשורה 142, פסיק חסר. מתברר שמדובר בהסתבכות קלאסית עם סוגריים, שכחנו לסגור את הסוגריים של קריאת ההתחברות למתערב, מאתרים את הסוגר החסר, מתקנים ומריצים שוב.
13. הצלחת החילוץ: אחרי התיקון הפונקציה מופעלת, מכניסים קלט בן עשרים וארבעה תווים, אחרת לא עוברים את הבדיקה, לוחצים על אימות, ומתקבלת על המסך המחרוזת הסודית כפי שהיא ביציאה מהפונקציה. ההדפסה של הזיכרון מראה את 24 הבתים ומנסה לתרגם אותם ל-ASCII, מה שלא עוזר כי אלה תווים מקודדים, וזו בדיוק המחרוזת שצריך לפענח.
14. פונקציית פענוח ו-XOR: כדי לא לכתוב את קוד הפענוח בתוך ההוק, יוצרים פונקציית עזר שמקבלת את המחרוזת המוצפנת ומחזירה את הפתרון. המחרוזת מועברת לפונקציה שהופכת כל ביט למספר, כך שמתקבל מערך של מספרים שאליו ניגשים איבר איבר. בלולאה של 24 איטרציות לוקחים את המספר הנוכחי, לוקחים מהמפתח את האות הנוחכת וממירים אותה לקוד ASCII, מבצעים XOR ביניהם, ממירים את המספר שהתקבל חזרה לתו, ואוספים את כל התווים יחד. העיקרון פשוט: פעולת XOR, רק שלפניה ממירים את המפתח לקודי ASCII.
15. הפענוח המוצלח: מריצים את הסקריפט המלא, מבצעים אימות, ומתקבל על המסך הסוד הגדול ואחריו התשובה האמיתית של האפליקציה, משפט באנגלית. הפענוח הצליח והאתגר השלישי נפרץ.
בשיעור הבא נעסוק בנושא פרויקט גמר בקורס האקינג לאפליציות אנדרואיד.
בסוף השיעור גילינו את המחרוזת הסודית בעזרת הוק על פונקציה פנימית שאינה מיוצאת, קראנו את ערכה מהזיכרון ביציאה מהפונקציה, ופענחנו אותה בפעולת XOR עם המפתח עד לקבלת התשובה הנכונה.
SR12607HE

פרקי ההרצאה: פריצה של UnCrackable-Level3

  1. 00:00

    המטרה: גילוי הסוד

  2. 00:55

    חזרה על InitSecretString

  3. 01:55

    הערך הנשמר בספרייה

  4. 02:49

    זיהוי פונקציה לפי כתובת

  5. 03:23

    חישוב הכתובת בזיכרון

  6. 04:20

    תפיסת הארגומנט בכניסה

  7. 05:17

    קריאת הסוד בזיכרון ביציאה

תמלול ההרצאה: פריצה של UnCrackable-Level3

הטקסט המלא של הדקות הראשונות בהרצאה «פריצה של UnCrackable-Level3» בקורס הווידאו של PracticU – כתוביות בעברית עם זמן התחלה לכל פסקה. כך תוכלו לקרוא ולחפש את הנושאים לפני שמתחילים ללמוד.

  1. 00:02

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

  2. 00:25

    כי צריך לקחת ולעשות לו קצור עם המפתח הסודי ורק כשנעשה קצור אנחנו נדע את התשובה הנכונה כי היא זאתי שמושווית פה ל-user input. אז בשביל שנגלה את הדבר הזה, את ה-key אנחנו יודעים כי הוא מהותחל ב-Java, ראינו שזה מילת פיצה כמה פעמים. השאלה זה, מה זה ה-secret string הזה?

  3. 00:46

    ויש לנו פונקציה שמאתחלת אותו. בואו ניכנס אליה ונראה. הנה הוא עושה את ה-compiling ובואו נראה את הפונקציה הזאתי. A1 זה בעצם ה-secret string שלי, זה האזור בזיכרון שלו.

  4. 00:59

    הרי זה מה שהעברנו לו, נכון? secret string זה הכתובת בזיכרון. אוקיי אז נעשה פה rename ונקרא לזה secret string address אוקיי ואני רואה פה תסתכלו על הבר הזה פה תראו תראו איזה ערוך זה וואי וואי וואי וואי וואי וואי וואי וואי יש פה מלא מלא פעולות שהם עושים אין לי מושג מה הם עושים בוא נלך לסוף הופה פה אני רואה שהוא לוקח את הריזולט מכניס את הכתובת התחילתית

  5. 01:32

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

  6. 01:57

    דבר כזה שמים את זה פה צד ימין ואנחנו צריכים לתפוס את הפונקציה הזאת עושה דאבל קליק מגיע לכאן, עושה לדבר הזה Synchronize with IWA, הנה שזה וזה יהיה מסונכרן, תחזור חזרה לכאן, הנה זאת הפונקציה שאנחנו רוצים להבין מה קורה, אני בא לפה לוחץ רווח,

  7. 02:19

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

  8. 02:31

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

  9. 02:40

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

  10. 02:55

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

  11. 03:23

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

  12. 03:40

    זאת הכתובת שאליה אנחנו רוצים להתחבר. הפעם אני לא רוצה לעשות Replace, אני רוצה לעשות Attach. למה אני רוצה לעשות Attach? כי אני רוצה להתחבר אליה.

  13. 03:49

    זוכרים, כמו שעשינו לפני כן? אני רוצה לעשות Attach כמו שעשינו פה למעלה. זוכרים שעשינו פה לפני ה-Replace, היה לנו פה Attach. אינטרספטור Attach ומתחברים לאיזושהי כתובת ותופסים ערך בכניסה, ביציאה יופי אז מה אני רוצה לעשות פה אני עושה attach לכתובת הזאת בזיכרון בכניסה אני תופס את הארגומנט הראשון שמועבר עליה נכון arg

  14. 04:15

    זה 0 שזה בעצם ה-secret string שלי וזה secret memory address secret string memory address פה בתוך arg 0 הזה יושב הערך הזה שמועבר לנו כאן בסוגריים סיקרט סטרינג אדרס הסיקרט סטרינג אדרס הזה הוא מועבר בסוגריים זה ארג אפס ואז אני עושה משתנה משלי ששומר את הערך פה זה הסוד הגדול ששמור ואני נכנס לתוך הפונקציה

  15. 04:43

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

  16. 05:17

    הרגע הזה שנגמרת פונקציית ההתחול והוא חוזר חזרה לקוד נכון הרי בסוף של הפונקציית התחול כאן הוא חוזר להלאה אז אני תופס אותו פה ביציאה כשהוא יוצא מפונקציית יעד חו"ל ויש לו פה את ה-Secret String המלא הזה.

  17. 05:33

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

  18. 05:42

    שוב אני מראה לכם, בכניסה תפסתי את הארגס 0, את הכתובת, ושמרתי אותה בצד ב-dis נקודה. למה דיס נקודה? שיהיה זמין ברמת ה-Object ולא רק ברמת פונקציה כדי שאני אוכל בפונקציה אחרת גם לתפוס אותו ואז אני תופס אותו כאן ביציאה, leave ואומר לו תקרא מתוך התא הזה בזיכרון 24 תווים ואז הוא קורא לי 24 תווים

  19. 06:08

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

  20. 06:31

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

לקורס המלא: קורס האקינג לאנדרואיד אונליין

ההרצאה הקודמת: ניתוח סטטי של UnCrackable3 עם IDA

הרצאות קשורות מקורסים אחרים

  • פריצה ל-SSH עם Hydra
  • XSS - פריצה לאתר עם Javascript
  • גילוי פריצה עם ETW - SilkETW
  • פריצה לאתר דרך כתובת URL

קורסים נוספים במסלול

  • קורס SOC - מיישם הגנת סייבר
  • קורס סייבר למתחילים - Hacking - בדיקות חוסן תשתיתי ופריצה ל-Windows 10/11 - קורס זה נדרש למבחן ההסמכה היוקרתי OSCP
  • קורס פריצה ומבדקי חדירה לתשתית ארגונית - בדיקות חוסן מתקדמות ל-Active Directory - קורס זה נדרש למבחן ההסמכה היוקרתי OSCP
  • קורס פריצה ומבדקי חדירה לאתרי אינטרנט - בדיקות חוסן לאתרים - Web Pentesting - קורס זה נדרש למבחן ההסמכה היוקרתי OSCP