שְׁאֵלָה:
הזרקת dll ו- GetProcAddress עם ה- winapi
lfxgroove
2013-09-14 20:20:45 UTC
view on stackexchange narkive permalink

אז פשוט קראתי קצת על האופן שבו ניתן היה להזריק dll לתוכנית פועלת בוויקיפדיה (הרעיון CreateRemoteThread ). עקבתי אחר השלבים המתוארים ובסופו של דבר הספקתי שזה עובד. הדבר שנראה לי מעניין, שלקח קצת זמן להבין הם הדברים הבאים: בעת יצירת השרשור המרוחק שלי ושליחת הפונקציה הייתי רוצה שיופעל כראשון / התחלתי פגעתי במלואו, כשהוא הופעל הוא נכשל כדי לקרוא לתפקודים המתאימים, נראה שהם הופכים לאשפה כשהסתכלתי עליהם ב- OllyDBG, מה שבתורו הביא לתוכנית להתרסק עלי. הקוד בו השתמשתי אז היה משהו בסגנון הבא:

  DWORD static __stdcall inject (LPVOID threadParam) {MessageBoxA (NULL, "test", "test", NULL); LoadLibrary ("my.dll"); להחזיר 0;}  

ובמקום אחר:

  CreateRemoteThreadEx (hProcess, NULL, 0, LPTHREAD_START_ROUTINE (fnPageBase), dbPageBase, 0, NULL, &threadId) ;  

היכן ש- fnPageBase הוא הזיכרון שהקצתי בתהליך שיוזרק לתפקוד שלי ו- dbPageBase הזיכרון שהקצתי עבור מבנה שהוא עבר כ LPVOID threadParam .

משהו כזה, הבעיה הייתה שגם MessageBoxA וגם LoadLibrary לא קיבלו נראה שזה כתובת נכונה, כשבדקתי אותם ב- OllyDBG הם תמיד הצביעו על משהו שלא היה קיים. חיפשתי קצת סביב וגיליתי שאני צריך להשתמש ב GetProcAddr כדי לקבל כתובת למשל: LoadLibrary בה אוכל להשתמש אחר כך על ידי שליחת נתונים דרך ה LPVOID threadParam בשיחה שלי inject () . אז השאלה שלי היא: מדוע זה עובד כשאני משתמש ב- GetProcAddr ולא כשאני פשוט מנסה להשתמש בו "כרגיל"? האם אני מקבל כתובת ספציפית שתמיד ממופה לכולם באותו אזור בזיכרון בעת ​​השימוש בה?

כמו כן, מה קורה למחרוזות שלי בפונקציה inject () ? האם הם עוברים למקום אחר במהלך הקומפילציה, מה שהופך אותם ללא זמינים לתוכנית שאני מזריק מכיוון שהיא נמצאת במקום אחר לגמרי בזיכרון (כלומר, היא לא ממופה לשם?)? עבדתי על ידי שליחת זה גם במבנה עם LPVOID threadParam גם במבנה שהעתקתי לזיכרון שזמין ל .exe שהזרקתי.

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

אחד תשובה:
Igor Skochinsky
2013-09-14 21:14:17 UTC
view on stackexchange narkive permalink

דבר אחד שעליך לזכור הוא שקוד בתהליך שלך והקוד בתהליך היעד נמצאים ב מרחבי כתובות שונים . אז כל כתובת בתוכנית שלך אינה הכרחית בתוקף בתהליך היעד ולהיפך.

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

זו הסיבה שהגישה הרגילה המשמשת ל CreateRemoteThreadEx היא להעתיק את שם ה- DLL תהליך היעד וצור את השרשור באמצעות כתובת הפונקציה LoadLibrary :

  // 1. הקצה זיכרון בתהליך המרוחק עבור szLibPathpLibRemote = :: VirtualAllocEx (hProcess , NULL, sizeof (szLibPath), MEM_COMMIT, PAGE_READWRITE); // 2. כתוב szLibPath לזיכרון שהוקצה :: WriteProcessMemory (hProcess, pLibRemote, (void *) szLibPath, sizeof (szLibPath), NULL); // טען את "LibSpy.dll" לתהליך המרוחק // (באמצעות CreateRemoteThread & LoadLibrary) hThread = :: CreateRemoteThread (hProcess, NULL, 0, (LPTHREAD_START_ROUTINE) :: GetProcAddress (hKernel32, "LoadLibraryA"), pote 0 NULL);  

(קטע מ- Project Project)

אתה יכול לראות ש- pLibRemote (עם הכתובת של שם ה- DLL בתהליך היעד) מועבר כפרמטר לשגרת החוטים. אז התוצאה של זה שווה ערך ל:

  LoadLibraryA (pLibRemote);  

מבוצע בתהליך היעד.

למען הדיוק, לא מובטח שזה יעבוד מכיוון שכתובת LoadLibraryA בתהליך שלך אינה בהכרח זהה ל- LoadLibraryA בתהליך האחר. עם זאת, בפועל זה אכן עובד מכיוון ש- DLL של המערכת כמו kernel32 (שם שוכן LoadLibraryA ) באותה כתובת בכל התהליכים, כך ש- LoadLibraryA יש גם אותה כתובת בשניהם תהליכים.

אז תיאורטית נוכל לטעות ולא לקבל כתובת ראויה גם כאשר אנו משתמשים ב- GetProcAddr? כמו כן, מדוע "ו- LoadLibraryA" לא יתנו כתובת טובה גם אם כולם ממופים לאותו אזור? האם צריך לפרסם זאת במקום אחר כשאלה נפרדת או שזה בסדר לשאול כאן?
'& LoadLibraryA' עשוי להחזיר מצביע לתאי הייבוא ​​בתהליך שלך ולא את הכתובת הסופית ב- 'kernel32.dll'.
חשבתי שבימינו עם רנדומיזציה של שטח התהליך אתה אפילו לא יכול לסמוך על כך ש- kernel32 ימופה באותה כתובת ... האם זה עדיין עובד גם ב- win7 / 8?
@LorenzoDematté: כתובת הטעינה של AFAIK של kernel32 אקראית בכל אתחול אך היא נשארת קבועה לאחר מכן.
טוב לדעת. וזה הגיוני, שכן מיפוי לאותה כתובת מאפשר שיתוף בין תהליכים.
אני מתחנן להבדיל, איגור. יש לקחת בחשבון * הרבה * יותר, כמו הפרדת המושב. אתה תדע למה אני מתכוון אם ניסית אי פעם לחצות את הגבול בין קוד שרץ בשירות לשולחן העבודה במערכת שווה או חדשה יותר מ- Vista. אין זמן לכתוב פרטים.
האם יש סיכוי שתקדיש את הזמן לעשות את זה איפה שהוא מתאים? יהיה מוערך מאוד!
@0xC0000022L: לא יצאתי לכתוב מדריך מפורט להזרקת DLL המכסה כל מקרה פינתי, פשוט ניסיתי לענות על השאלה המוצהרת (והוספתי מעט רקע). אם עשיתי טעויות ספציפיות, אנא ציין אותן.


שאלה ותשובה זו תורגמה אוטומטית מהשפה האנגלית.התוכן המקורי זמין ב- stackexchange, ואנו מודים לו על רישיון cc by-sa 3.0 עליו הוא מופץ.
Loading...