מילון מושגים:
USB - תקן חיבור אוניברסלי לחיבור התקנים למחשב, כמו זיכרון נייד, מקלדת או מדפסת.
GitHub - שירות ענן לאחסון מאגרי קוד מבוססי Git, המאפשר שיתוף פעולה, מעקב גרסאות וניהול פרויקטים.
באג - תקלה או שגיאה בקוד שגורמת לתוכנה להתנהג בניגוד למצופה.
שורת פקודה - ממשק טקסטואלי שבו מקלידים פקודות למערכת ההפעלה ומקבלים תגובה בטקסט, במקום להשתמש בעכבר.
JavaScript - שפת תכנות שרצה בעיקר בדפדפן ומוסיפה אינטראקטיביות לדפי אינטרנט. רצה גם בצד השרת באמצעות Node.js.
Java - שפת תכנות עילית ומונחית עצמים, הרצה על מכונה וירטואלית (JVM) ומשמשת לפיתוח מגוון יישומים.
מעטפת - תוכנה שמפרשת פקודות של המשתמש ומעבירה אותן למערכת ההפעלה, למשל Bash או PowerShell.
Activity - ב-Android, רכיב שמייצג מסך יחיד של האפליקציה שאיתו המשתמש מתקשר.
כתיבת סקריפט Frida עבור UnCrackable
בשיעור זה נכתוב את סקריפפ ה Frida הראשון שלנו, סקריפפ פשוט שמחליף בזיכרון של המכשיר את פונקציות זיהוי השורש של אפליקציה תמימה לכאורה, כך שהיא תעבוד על מכשיר פרוץ במקום להיסגר. נעבור את כל התהליך, מהורדת האפליקציה והנדסה לאחור של הקוד שלה ועד הזרקת הסקריפף בזמן אמת.
נושאי הסיכום המוצגים בשיעור:
1. הסביבה: עובדים מול הטלפון הווירטואלי של Genymotion, שמאחורי הקלעים הוא מכונה וירטואלית של Virtual Box שהתוכנה מנהלת לבדה. אפשר לחבר גם טלפון פיזי בעזרת USB, אך עדיף לא להרוס טלפון אמיתי ולכן עובדים על הווירטואלי.
2. אפליקציית המטרה: מורידים מה GitHub את UnCrackable ברמה הראשונה של OWASP, הארגון שאוסף באגים ופריצות אבטחה בווב והכין גם אפליקציות מובייל לתרגול ברמות שונות. בודקים בעזרת adb devices שיש תקשורת עם הטלפון, מתקינים את ה APK בעזרת adb install, ומוחקים את העותק המקומי מהדיסק כדי לדמות מצב שבו האפליקציה קיימת רק בתוך הטלפון.
3. למה דווקא האפליקציה הזאת: בהפעלה היא מודיעה שהמכשיר פרוץ ומסרבת לעבוד, ואנחנו רוצים לשנות בזמן אמת, בתוך הזיכרון של האפליקציה, את הזיהוי הזה. בחרנו בה ולא באפליקציית הבנק מפני שכאן זיהוי השורש הוא מסך הפתיחה עצמו וזה פשוט יותר, ואת הבנק נעשה אחרי כן.
4. רשימת האפליקציות: בעזרת frida ps עם המתג של USB מוצגות גם האפליקציות הרצות וגם האלה שמותקנות בלבד, ובהן אפליקציית המטרה שלנו וגם פרידה עצמה.
5. התיקיות החשובות במכשיר: בתוך המכשיר, בשורת הפקודה שלו, מעניינות אותנו שתי תיקיות. data data הוא המקום שבו כל אפליקציה שמה את הנתונים שלה, ו data app הוא המקום שבו מוחזקות האפליקציות עצמן, כלומר קובצי ה APK המותקנים. מאתרים בתוכו את החבילה שלנו לפי שמה ורואים את קובץ ה APK עצמו.
6. שליפת ה APK מהמכשיר: אחרי יציאה מהמכשיר מריצים adb pull ומושכים את קובץ ה APK מתוך תיקיית ה data app אל התיקייה הנוכחית במחשב. כך התקבל מחדש קובץ ההתקנה שמחקנו קודם, הפעם ישירות מהמכשיר.
7. הנדסה לאחור בעזרת JADX: משליכים את הקובץ אל תוך JADX, כפי שעשינו בשיעורים קודמים, והוא מנתח אותו ומציג את החבילות והקוד שבתוכן, ביניהן מחלקות וחלונות שונים. במקום לחפש ביד משתמשים בחיפוש של הכלי.
8. איתור קוד הזיהוי: מפעילים את האפליקציה ומעתיקים את ההודעה שהיא מציגה על זיהוי שורש, מחפשים אותה בחיפוש של JADX בתוך הקוד, ומגיעים ישירות אל השורה שבה היא נכתבה. כך מבוצעת הנדסה לאחור על קובץ שנשלף מהטלפון.
9. ההיגיון של הזיהוי: השורה היא תנאי שבודק אם מחלקה מסוימת, שנקראת C, מחזירה אמת מאחת משלוש פונקציות הבדיקה שלה. אם אחת משלוש הבדיקות מחזירה אמת, מוצגת הודעת זיהוי השורש והאפליקציה מסתיימת. מזהים את הפונקציות בלחיצת עכבר תוך החזקת קונטרול, וכל אחת מהן בודקת משהו ומחזירה אמת או שקר.
10. מה רוצים להשיג: להחליף בזיכרון את שלוש הבדיקות כך שכולן יחזירו שקר, ואז אף אחת מהן לא תצביע על מכשיר פרוץ והאפליקציה תמשיך לרוץ. המחלקה C שמכילה את שלוש הפונקציות יושבת בתוך החבילה ששמה ידוע לנו, וכל מה שדרוש הוא שם החבילה, שם המחלקה ושמות הפונקציות.
11. הסקריפף עצמו: הסקריפף כתוב בשפת JavaScript, פותחים אותו בעורך טקסט פשוט, והוא זמין גם בשרת הקבצים של הקורס. בתחילתו הוא מדפיס על המסך שהתחיל חיבור, Start Hooking, והמילה hooking פירושה להתחבר אל תוך פונקציה או אל הקוד, בדיוק כפי שמתחבר דבאגר אל תוכנה, וכמו דבאגר רק אחד יכול להיות מחובר בכל רגע. אחר כך ישנה פונקציה בשם my bypass שהסקריפף מפעיל דרך Java perform, ובתוכה מוכרז משתנה שמקבל את תוצאת Java use על השם המלא של המחלקה, שם החבילה ושם המחלקה, וכך המשתנה מצביע אל אותה מחלקה בזיכרון המכשיר.
12. החלפת הפונקציות: אחרי שיש לנו מצביע אל המחלקה, מבקשים ממנו החלפה של פונקציית A במימוש חדש, implementation, כלומר קוד חדש שמחליף לגמרי את כל הקוד המקורי של הפונקציה. הקוד החדש מדפיס על המסך שבוצעה עקיפה של בדיקת השורש במחלקה ובפונקציה הספציפית, ומחזיר שקר. את אותו דבר עושים גם לפונקציית B וגם לפונקציית C, מצביעים על אותה מחלקה ומחליפים כל אחת מהן בקוד שמחזיר שקר.
13. הזרקת הסקריפף: מריצים את פרידה עם המתג של USB, כי ייתכן שמחוברים כמה מכשירים, עם שם קובץ הסקריפף, עם המתג שמורה לה להפעיל את האפליקציה עצמה, ועם המתג שאומר שלא לעצור, No Pause. חשוב לעמוד באותה תיקייה שבה נמצא קובץ הסקריפף, אחרת הכלי לא ימצא אותו. הניסיון הראשון נכשל בהודעה שלא ניתן להתחבר אל הרכיב במכשיר, מפני ששכחנו להפעיל את שרת פרידה בתוך הטלפון.
14. הפעלת שרת פרידה בטלפון: נכנסים בעזרת adb shell אל תיקיית ה temp של המכשיר, שם כבר יושב קובץ השרת מהשיעור הקודם, ומריצים אותו עם סימן הרצה ברקע, והוא מתחיל לעבוד מאחורי הקלעים על הפורט שלו. אחרי שהשרת רץ מריצים שוב את הזרקת הסקריפף, והפעם מודפס שהחיבור התחיל, הכלי יוצר את האפליקציה, מזריק לתוכה את הסקריפף, ממשיך להריץ אותה בעצמו, והאפליקציה עובדת בלי לזהות שום דבר ומדפיסה את הודעות העקיפה של שלוש הפונקציות.
15. מצב אינטראקטיבי: בלי המתג שאומר לא לעצור, פרידה טוענת את האפליקציה ואת הסקריפף אל הזיכרון ועוצרת לפני הפקודה הראשונה וממתינה להוראות. שם אפשר להריץ resume שממשיך את הריצה, ולראות שאחרי ההמשך ההודעות מגיעות, ואפשר לטעון סקריפף נוסף בעזרת load. סגירת האפליקציה מנתקת את החיבור של פרידה. השיטה שהוצגה עובדת רק על המסך הראשון שהכלי מפעיל, מפני שאיננו יודעים כיצד להורות לו להפעיל activity אחר, ובאפליקציית הבנק דרוש דווקא ה activity המוצהר כ exported של אחרי ההתחברות, ולכן בשיעור הבא נעבוד בשיטה מורכבת יותר שבה ההרצה נעשית מתוך פייתון, עם אותם עקרונות בדיוק.
בשיעור זה שלפנו את ה APK מתוך המכשיר, פתחנו אותו ב JADX, איתרנו את קוד זיהוי השורש לפי ההודעה שהוא מציג, הבנו את שלוש הבדיקות שמחזירות אמת או שקר, כתבנו סקריפפ פרידה שמחליף אותן בזיכרון בקוד שמחזיר שקר, הפעלנו את שרת פרידה בתוך הטלפון והזרקנו את הסקריפף בעת הפעלת האפליקציה, והיא עבדה בלי לזהות דבר. בשיעור הבא נעסוק בנושא כתיבת סקריפפ פרידה עבור InsecureBank.
SR12581HE