טיול קצר בתכנות דרייברים
מדריך לכתיבת דרייבר בסיסי עבור כל גרסאות Windows
לפני כשבועיים פרסם אחד מחברי פורום ההאקינג הישראלי (Ratinho) אתגר מעניין. קראק-מי פשוט שמבקש סיסמה ומחזיר Good job או Wrong password בהתאם. המטרה הייתה לפרוץ את התוכנה שתחזיר תמיד Good job, גם אם הוכנסה סיסמה לא נכונה, ומכיוון שההשוואה מתבצעת בעזרת קריאה פשוטה ל-lstrcmp בלי שום נסיון להסתיר או לסבך משהו, כל מה שצריך לעשות זה לשנות את ה-JNZ שאחריה ל-JMP.
מה שהפך את האתגר למעניין היה התנאי – הפתרון חייב להיות חיצוני, ללא שום שינוי בתוכנה. ראיתי את האתגר בדיוק אחרי שכתבתי את המאמר על הזרקת DLL בשולה המוקשים, ובעזרת אותה טכניקה פשוט לשנות את קוד התוכנה בזיכרון.
אבל אז זה היה פשוט מדי, ורציתי להיות מקורי יותר. אז מה שעשיתי היה לשכתב (Inline Hooking) את lstrcmp שבתוך Kernel32 שתחזיר תמיד 0 (המחרוזות שוות). כל תהליך טוען את המודולים למרחב הכתובות שלו (באופן תאורטי לפחות), ככה שהשינוי השפיע רק על הקראק-מי (קוד מקור, לרשימת הפתרונות).
חשבתי שהייתי מקורי, עד שראיתי את הפתרון שהציע Zerith, משתמש אחר בפורום. הוא הפתיע את כולם בסיבוך של הפתרון שלו… הוא כתב דרייבר שעושה הוקינג להנדלר של ה-Page Fault (אפשר לקרוא על זה בוויקיפדיה, אבל מה שחשוב לנו הוא שכל פעם שמערכת ההפעלה צריכה קטע שלא נמצא בזיכרון בפועל, Page Fault קורה), שברגע שקורה Page Fault, אם הוא קוד הקראק מי, במקום לטעון את הקוד מהדיסק הוא מכניס בעצמו קוד שכבר פרוץ (שינוי של ה-JMP).
התלהבתי כשראיתי את זה, והחלטתי שאני חייב ללמוד את הנושא לעומק. אז התחלתי 🙂