דילוג לתוכן
  • חוקי הפורום
  • פופולרי
  • לא נפתר
  • משתמשים
  • חיפוש גוגל בפורום
  • צור קשר
עיצובים
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • ברירת מחדל (ללא עיצוב (ברירת מחדל))
  • ללא עיצוב (ברירת מחדל)
כיווץ
מתמחים טופ
  1. דף הבית
  2. מחשבים וטכנולוגיה
  3. עזרה הדדית - מחשבים וטכנולוגיה
  4. שיתוף | יכול להיות שבניתי את התוכנה הכי קטנה בעולם?

שיתוף | יכול להיות שבניתי את התוכנה הכי קטנה בעולם?

מתוזמן נעוץ נעול הועבר עזרה הדדית - מחשבים וטכנולוגיה
25 פוסטים 11 כותבים 602 צפיות 11 עוקבים
  • מהישן לחדש
  • מהחדש לישן
  • הכי הרבה הצבעות
תגובה
  • תגובה כנושא
התחברו כדי לפרסם תגובה
נושא זה נמחק. רק משתמשים עם הרשאות מתאימות יוכלו לצפות בו.
  • יאיר דניאלי יאיר דניאל

    לא עובד לי
    cc637373-713d-4fa4-9727-09578a80bc28-image.png

    עריכה: זה היה רק במחשב מסויים - במחשב שלי עובד מצויין

    מתכנת חובבמ מנותק
    מתכנת חובבמ מנותק
    מתכנת חובב
    מדריכים
    כתב נערך לאחרונה על ידי
    #15

    @יאיר-דניאל אני בודק את זה
    אולי מדובר ב build לא תואם אבל מעניין

    צריך עזרה בשחזור מידע? ייעוץ? egozkokus1@gmail.com

    1 תגובה 1 תגובה אחרונה
    1
    • מתכנת חובבמ מתכנת חובב

      @יאיר-דניאל אני בודק את זה
      אולי מדובר ב build לא תואם אבל מעניין

      1 מנותק
      1 מנותק
      106
      כתב נערך לאחרונה על ידי
      #16

      @מתכנת-חובב עבד להפליא כבר בפעם הראשונה
      9f925f36-8e77-4985-8bf9-a91ca50da3a4-תמונה.png

      מתכנת חובבמ תגובה 1 תגובה אחרונה
      0
      • ה מנותק
        ה מנותק
        המלאך
        כתב נערך לאחרונה על ידי
        #17

        @מתכנת-חובב מאוד יפה!
        אהבתי את הרעיון.

        תגובה 1 תגובה אחרונה
        0
        • 1 106

          @מתכנת-חובב עבד להפליא כבר בפעם הראשונה
          9f925f36-8e77-4985-8bf9-a91ca50da3a4-תמונה.png

          מתכנת חובבמ מנותק
          מתכנת חובבמ מנותק
          מתכנת חובב
          מדריכים
          כתב נערך לאחרונה על ידי
          #18

          @106 עבדתי מאוד קשה כדי שיעבוד בפעם הראשונה...
          תכלס יש מחשבים שזה נפל בהם בגלל שווינדוס לפעמים קצת חצוף (אולי מחר אני יכתוב הסבר מסודר על תהליך הבניה)
          אבל עבדתי קשה והצלחתי
          עכשיו יש גרסה שבעזרת השם תעבוד אצל כולם

          צריך עזרה בשחזור מידע? ייעוץ? egozkokus1@gmail.com

          תגובה 1 תגובה אחרונה
          7
          • מתכנת חובבמ מתכנת חובב

            נחשפתי לאחרונה לעולם של התוכנות הזעירות - אמנות שבה דוחסים שדות בקובץ exe אחד על השני ומצמצמים את הקוד עצמו למינימום ו"עובדים" על ה loader של ווינדוס כמה שאפשר
            הגודל המינימלי של התוכנות האלו נכון להיום הוא 268 בתים בגלל דרישות יישור ולכאורה מבנה ה struct שה loader של ווינדוס מחפש לקרוא כשהוא פותח קובץ
            הקבצים שראיתי ברשת (האמת שלא חקרתי הרבה) - כל מה שהם עושים היה סך הכל לבצע return ל loader או סתם להגדיר ערך כלשהו ב EAX אבל לא באמת משהו מעניין
            אז ישבתי להכין תוכנת hello world שתשב באותו גודל מינימלי והצלחתי אפילו יותר - יש לי 2 בתים ריקים בסוף שהשארתי שם 00 בשביל הריפוד לגודל הנדרש ככה שסך כל הגודל של התוכנה הוא 266 בתים!
            הבניה של זה הייתה די מסובכת ולקחה לי כמה שעות של מלחמות עם ווינדוס ואסמבלי ובשלב מסויים גם עם הבינארי עצמו (וגיליתי שלא כזה מסובך לעשות patching ידני ל opcodes)
            ממה שבדקתי זאת תוכנת ה hello world הכי קטנה בעולם אבל אולי יש משהו שמנצל אפילו פחות או עושה דברים נוספים (ניסיתי לגרום לו גם לצפצף אבל זה דרש כבר שכתוב של כל ה opcodes וסדר הריצה ואין לי זמן \ כוח לזה עכשיו אבל זה נראה אפשרי) - אם מישהו ימצא משהו טוב יותר אשמח אם הוא יוכל ליידע אותי
            אם מעניינים פרטים טכניים על הקובץ והבניה שלו - תוכלו לבקש ואשמח לשתף
            בדקתי את הקובץ אצלי - גרסת build 26200.7840 אבל יכול להיות שבעדכוני ווינדוס הבאים זה יישבר
            מצורף הקובץ וה dump שלו למי שמתעניין
            smallest_hello_world.exe

            עריכה: אחרי ששמעתי ממשתמשים שהתוכנה קרסה אצלם מתברר שיש גרסאות של ווינדוס שבהם מתבצעות בדיקות שונות ולעשות תוכנה אחת שתעבוד אצל כולם זה חתיכת סיפור
            אחרי שסידרתי את עניין ה IAT קפץ עלי רוגזה של בדיקת DRM בגלל דגל debugging לא מאופס (הוא נופל אצלי בדיוק באמצע הקוד...) מקווה שאצליח לסדר את זה
            עריכה: סודר
            אם קורס אצלכם אשמח שתודיעו לי

            4D 5A 00 00 50 45 00 00 4C 01 00 00 68 65 6C 6C 6F 20 77 6F 72 6C 64 21 00 00 02 01 0B 01 FF FF FF FF FF 75 73 65 72 33 32 00 00 FF 88 00 00 00 6D 69 74 6D 2E 74 6F 70 00 00 40 00 04 00 00 00 04 00 00 00 06 00 00 00 00 00 00 00 06 00 00 00 00 00 00 00 0C 01 00 00 6F 00 00 00 00 00 00 00 02 00 00 00 00 00 10 00 00 10 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 BF A8 A2 4D BC EB 31 00 00 00 00 00 64 A1 30 00 00 00 8B 40 0C 8B 40 14 8B 00 8B 00 8B 68 10 BF 8E 4E 0E EC E8 23 00 00 00 68 23 00 40 00 FF D0 95 EB CD 90 00 00 00 00 E8 11 00 00 00 6A 00 68 30 00 40 00 68 0C 00 40 00 6A 00 FF D0 C3 8B 55 3C 8B 54 15 78 01 EA 8B 4A 18 8B 5A 20 01 EB 49 8B 34 8B 01 EE 52 31 C0 99 AC 84 C0 74 07 C1 CA 0D 01 C2 EB F4 39 FA 5A 75 E5 8B 5A 24 01 EB 0F B7 0C 4B 8B 5A 1C 01 EB 03 2C 8B 89 E8 C3 00 00
            

            c2bdc5e4-1e9f-4048-b739-ce3a04c47cbf-image.png

            עריכה: יצאה גרסה מעודכנת וסופית
            https://mitmachim.top/topic/93863/שיתוף-התוכנה-הכי-קטנה-בעולם-עכשיו-גם-מנגנת

            א מנותק
            א מנותק
            אביגדור ברמן
            כתב נערך לאחרונה על ידי
            #19

            @מתכנת-חובב
            בבתים ששלחת:
            6D 69 74 6D 2E 74 6F 70 מתרגם ל-mitm.top. ! ! !

            זה מופיע מיד אחרי המחרוזת hello world!, מה שמחזק את ההשערה שמדובר בתוכנית דוגמה קטנה שנכתבה על ידי אחד מחברי הקהילה שם כדי להדגים יכולות תכנות ב-Assembly או מניפולציה של קבצי EXE.

            מתכנת חובבמ תגובה 1 תגובה אחרונה
            1
            • א אביגדור ברמן

              @מתכנת-חובב
              בבתים ששלחת:
              6D 69 74 6D 2E 74 6F 70 מתרגם ל-mitm.top. ! ! !

              זה מופיע מיד אחרי המחרוזת hello world!, מה שמחזק את ההשערה שמדובר בתוכנית דוגמה קטנה שנכתבה על ידי אחד מחברי הקהילה שם כדי להדגים יכולות תכנות ב-Assembly או מניפולציה של קבצי EXE.

              מתכנת חובבמ מנותק
              מתכנת חובבמ מנותק
              מתכנת חובב
              מדריכים
              כתב נערך לאחרונה על ידי
              #20

              @אביגדור-ברמן מה אתה בא לומר?
              די ברור שזה מה שרציתי לעשות

              צריך עזרה בשחזור מידע? ייעוץ? egozkokus1@gmail.com

              א תגובה 1 תגובה אחרונה
              1
              • מתכנת חובבמ מתכנת חובב

                @אביגדור-ברמן מה אתה בא לומר?
                די ברור שזה מה שרציתי לעשות

                א מנותק
                א מנותק
                אביגדור ברמן
                כתב נערך לאחרונה על ידי
                #21

                @מתכנת-חובב זה מגניב!
                (אני לא מבין בזה, זה הגברת בינה...)

                תגובה 1 תגובה אחרונה
                1
                • cfopuserC מנותק
                  cfopuserC מנותק
                  cfopuser
                  כתב נערך לאחרונה על ידי
                  #22

                  מרשים מאוד.

                  534c21b3-7f7c-4809-b995-e17e8c026e30-image.png

                  תגובה 1 תגובה אחרונה
                  1
                  • iosi poliI מנותק
                    iosi poliI מנותק
                    iosi poli
                    כתב נערך לאחרונה על ידי
                    #23

                    עבד בפעם הראשונה 🙂
                    מאסטר האסמבלי..

                    תגובה 1 תגובה אחרונה
                    1
                    • מתכנת חובבמ מתכנת חובב התייחס לנושא זה
                    • א מנותק
                      א מנותק
                      אביגדור ברמן
                      כתב נערך לאחרונה על ידי אביגדור ברמן
                      #24

                      גיפיטי מסביר מה הולך שם בבינארי - בספויילר

                      הסבר טכני תמציתי, שלב-אחר-שלב, למה שהקובץ עושה בפועל:

                      1. טעינה ע״י ה-Loader

                      תחילת הקובץ מכילה חתימות MZ ו-PE\0\0.

                      ה-Loader של Windows מזהה זאת כ-PE, ממפה את ה-Image לזיכרון לפי ה-headers ומקפיץ ל-EntryPoint.

                      1. אין Import Table רגילה

                      ה-DataDirectory של Imports ריק/לא בשימוש.

                      לכן אין IAT סטטית.

                      במקום זאת הקוד פותר APIs בזמן ריצה (manual resolving).

                      1. קבלת כתובת בסיס של מודולים (גישה ל-PEB)

                      ב-EntryPoint מתבצעת גישה ל-PEB דרך ה-segment register (ב-x86 דרך ‎FS:[0x30]‎).

                      מהלך טיפוסי:

                      קריאה ל-PEB

                      כניסה ל-PEB_LDR_DATA

                      מעבר על רשימת InMemoryOrderModuleList

                      כך מאתרים את:

                      ‎kernel32.dll‎ (כבר טעון בתהליך)

                      1. מציאת Export Table של kernel32

                      לאחר שיש BaseAddress של kernel32:

                      קריאת offset ‎e_lfanew‎ מתוך DOS header

                      קפיצה ל-NT Headers

                      גישה ל-DataDirectory → Export Table

                      חישוב כתובות:

                      AddressOfNames

                      AddressOfFunctions

                      AddressOfNameOrdinals

                      1. לולאת Hash על שמות פונקציות

                      הקוד עובר על כל שם פונקציה ב-Export Table:

                      מבנה אופייני שנראה אצלך:

                      AC
                      84 C0
                      74 07
                      C1 CA 0D
                      01 C2

                      זו לולאה שמבצעת:

                      קריאה תו-תו

                      rotate right

                      הוספת ערך

                      יצירת hash

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

                      בדרך זו מאתרים:

                      LoadLibraryA

                      GetProcAddress

                      1. טעינת user32.dll

                      אחרי שיש כתובת של LoadLibraryA:

                      הקוד קורא לה עם המחרוזת "user32"

                      מתקבלת כתובת בסיס של user32.dll

                      1. מציאת MessageBoxA

                      שוב מתבצע:

                      סריקת Export Table של user32

                      חישוב hash

                      התאמה ל-MessageBoxA

                      קבלת ה-function pointer

                      1. קריאה ל-MessageBoxA

                      ה-stack נבנה ידנית:

                      סדר הפרמטרים (stdcall):

                      push 0 ; hWnd
                      push "hello world!" ; lpText
                      push "hello world!" ; lpCaption (או דומה)
                      push 0 ; uType
                      call MessageBoxA

                      לכן מתקבלת תיבת הודעה עם הטקסט.

                      1. יציאה

                      לאחר הקריאה:

                      מתבצע ret או קריאה ל-ExitProcess (גם כן נפתר דינמית או פשוט חזרה ל-loader).

                      למה זה עובד בלי Import Table?

                      כי:

                      הכל מחושב בזמן ריצה.

                      אין תלות ב-IAT.

                      ה-Loader רק צריך למפות את ה-image ולהריץ את ה-EntryPoint.

                      מה זה בפועל?

                      PE מינימלי עם:

                      API hashing

                      Manual export resolving

                      ללא imports סטטיים

                      ללא sections מורכבות

                      זו טכניקה נפוצה בקבצים קומפקטיים מאוד וב-shellcode.

                      פירוט ממוקד לפי הרצף הבינארי ששלחת, משלב ה-EntryPoint והלאה (x86):

                      שלב 1 — כניסה וניווט ל-Export Table של kernel32

                      הרצף:

                      8B 55 3C
                      8B 54 15 78
                      01 EA

                      פירוק:

                      8B 55 3C
                      mov edx, [ebp+3Ch]
                      קריאת ‎e_lfanew‎ (offset ל-NT headers).

                      8B 54 15 78
                      mov edx, [ebp+edx+78h]
                      גישה ל-DataDirectory → Export Table.

                      01 EA
                      add edx, ebp
                      המרה מ-RVA לכתובת מוחלטת.

                      עכשיו EDX מצביע ל-IMAGE_EXPORT_DIRECTORY.

                      שלב 2 — שליפת טבלאות ה-Export

                      הרצף:

                      8B 4A 18
                      8B 5A 20
                      01 EB
                      49

                      פירוק:

                      8B 4A 18
                      mov ecx, [edx+18h]
                      NumberOfNames.

                      8B 5A 20
                      mov ebx, [edx+20h]
                      AddressOfNames (RVA).

                      01 EB
                      add ebx, ebp
                      EBX עכשיו מצביע למערך שמות.

                      49
                      dec ecx
                      התחלת לולאה.

                      שלב 3 — לולאת hash על שמות פונקציות

                      הרצף:

                      8B 34 8B
                      01 EE
                      52
                      31 C0
                      99
                      AC
                      84 C0
                      74 07
                      C1 CA 0D
                      01 C2
                      EB F4

                      פירוק לוגי:

                      8B 34 8B
                      mov esi, [ebx+ecx*4]
                      קבלת RVA של שם פונקציה.

                      01 EE
                      add esi, ebp
                      המרה לכתובת.

                      31 C0
                      xor eax,eax
                      hash = 0.

                      לולאת תווים:

                      AC → lodsb (טעינת תו)

                      84 C0 → test al,al (סוף מחרוזת?)

                      74 07 → אם 0 → יציאה

                      C1 CA 0D → ror edx,13 (rotate)

                      01 C2 → add edx,eax (עדכון hash)

                      EB F4 → חזרה ללולאה

                      זו לולאת hashing טיפוסית לזיהוי פונקציות בלי להשאיר שמות גלויים.

                      שלב 4 — התאמת hash

                      הרצף:

                      39 FA
                      5A
                      75 E5

                      39 FA → cmp edx, edi (השוואת hash לערך קשיח)

                      75 E5 → אם לא שווה → המשך לולאה

                      כאשר נמצא hash תואם → ממשיכים לשליפת הכתובת.

                      שלב 5 — שליפת כתובת פונקציה

                      הרצף:

                      8B 5A 24
                      01 EB
                      0F B7 0C 4B
                      8B 5A 1C
                      01 EB
                      03 2C 8B

                      פירוק:

                      8B 5A 24
                      AddressOfNameOrdinals

                      0F B7 0C 4B
                      movzx ecx, word [ebx+ecx*2]
                      קבלת ordinal

                      8B 5A 1C
                      AddressOfFunctions

                      03 2C 8B
                      הוספת offset של הפונקציה

                      בסיום — מתקבל pointer לפונקציה (למשל LoadLibraryA).

                      שלב 6 — קריאה ל-LoadLibraryA

                      בהמשך מופיע:

                      6A 00
                      68 30 00 40 00
                      68 0C 00 40 00
                      6A 00
                      FF D0

                      פירוק:

                      push 0

                      push offset string

                      push offset string

                      push 0

                      FF D0 → call eax

                      EAX מכיל pointer לפונקציה שנפתרה.

                      כאן נטענת "user32".

                      שלב 7 — פתרון MessageBoxA

                      אותו תהליך hash מתבצע על export table של user32.dll עד למציאת MessageBoxA.

                      שלב 8 — קריאה ל-MessageBoxA

                      Stack נבנה כך:

                      push 0
                      push "hello world!"
                      push "hello world!"
                      push 0
                      call MessageBoxA

                      ולכן מתקבלת תיבת הודעה עם המחרוזת שמופיעה בקובץ:

                      68 65 6C 6C 6F 20 77 6F 72 6C 64 21
                      מה זה בפועל?

                      אין Import Table

                      אין IAT

                      כל ה-API נפתר דינמית

                      hashing כדי להימנע משמות גלויים

                      PE מינימלי עם loader ידני

                      זו טכניקת manual export resolving מלאה.

                      פירוק מבנה ה-PE עצמו — למה ה-Loader עדיין מוכן להריץ אותו למרות שהוא מינימלי מאוד.

                      1. DOS Header

                      התחלה:

                      4D 5A ; "MZ"
                      ...
                      3C ?? ?? ?? ?? ; e_lfanew

                      4D 5A = חתימת DOS תקינה.

                      ב-offset ‎0x3C‎ נמצא ‎e_lfanew‎ — מצביע ל-NT Headers.

                      ה-DOS stub כמעט לא קיים — אבל זה לא קריטי. ה-Loader צריך רק:

                      חתימה תקינה

                      offset חוקי ל-PE

                      1. NT Headers

                      בכתובת שמצביע ‎e_lfanew‎:

                      50 45 00 00 ; "PE\0\0"
                      4C 01 ; Machine = 0x14C (x86)
                      01 00 ; NumberOfSections = 1

                      זה מספיק כדי להיחשב PE תקני ל-32 ביט.

                      1. Optional Header (PE32)

                      החתימה:

                      0B 01 ; PE32 (לא PE32+)

                      שדות קריטיים שה-Loader חייב:

                      AddressOfEntryPoint

                      ImageBase

                      SectionAlignment

                      FileAlignment

                      SizeOfImage

                      SizeOfHeaders

                      Subsystem

                      גם אם הערכים מינימליים מאוד — כל עוד הם עקביים לוגית, ה-Loader ימשיך.

                      1. DataDirectory

                      Import Directory כאן ריק או לא שמיש.

                      זה חוקי.

                      Windows לא מחייב Import Table — רק אם יש אחת, הוא יטפל בה.

                      במקרה שלך:

                      אין IAT שימושית

                      לכן אין צורך ב-relocation imports

                      הכל נעשה בקוד

                      1. Section Table

                      מוגדרת Section אחת בלבד (למשל ‎.text‎ או אפילו בלי שם משמעותי).

                      ה-Loader צריך:

                      VirtualAddress

                      VirtualSize

                      SizeOfRawData

                      PointerToRawData

                      Characteristics עם:

                      IMAGE_SCN_MEM_EXECUTE

                      IMAGE_SCN_MEM_READ

                      אם ה-Section מסומנת executable — זה מספיק.

                      1. מיפוי לזיכרון

                      בעת הרצה:

                      Windows מקצה זיכרון בגודל ‎SizeOfImage‎.

                      מעתיק את ה-Headers.

                      מעתיק את ה-Section ל-VirtualAddress.

                      קופץ ל-ImageBase + AddressOfEntryPoint.

                      אין צורך ב-IAT כי אין Imports לעבד.

                      1. למה אין צורך ב-Relocations?

                      אם:

                      ImageBase תואם למה שה-Loader מצליח להקצות
                      או

                      הקוד משתמש ב-RVA יחסיים

                      אז relocation table לא חובה.

                      ב-PE מינימליים לעיתים:

                      פשוט מניחים ImageBase סטנדרטי

                      ואם הוא פנוי — הכל עובד

                      1. למה Windows לא “דורש יותר”?

                      ה-Loader בודק מינימום:

                      חתימות תקינות

                      מבנה NT headers סביר

                      Section Table חוקית

                      EntryPoint בתוך טווח section executable

                      זהו.

                      כל השאר אופציונלי.

                      סיכום מבני

                      הקובץ שלך הוא:

                      DOS header מינימלי

                      NT headers תקינים

                      Section אחת

                      ללא Import Table

                      ללא IAT

                      ללא Relocations משמעותיות

                      EntryPoint שמבצע manual resolving

                      לכן:

                      ה-Loader עושה רק mapping → קפיצה ל-EntryPoint → ומשם הכל קורה בקוד שלך.

                      @מתכנת-חובב - כמה אחוז ממה שהוא כתב נכון?

                      נ.ב. אני הבנתי רק 3 אחוז ממה שהוא כתב, (וגם זה גוזמה)

                      מתכנת חובבמ תגובה 1 תגובה אחרונה
                      0
                      • א אביגדור ברמן

                        גיפיטי מסביר מה הולך שם בבינארי - בספויילר

                        הסבר טכני תמציתי, שלב-אחר-שלב, למה שהקובץ עושה בפועל:

                        1. טעינה ע״י ה-Loader

                        תחילת הקובץ מכילה חתימות MZ ו-PE\0\0.

                        ה-Loader של Windows מזהה זאת כ-PE, ממפה את ה-Image לזיכרון לפי ה-headers ומקפיץ ל-EntryPoint.

                        1. אין Import Table רגילה

                        ה-DataDirectory של Imports ריק/לא בשימוש.

                        לכן אין IAT סטטית.

                        במקום זאת הקוד פותר APIs בזמן ריצה (manual resolving).

                        1. קבלת כתובת בסיס של מודולים (גישה ל-PEB)

                        ב-EntryPoint מתבצעת גישה ל-PEB דרך ה-segment register (ב-x86 דרך ‎FS:[0x30]‎).

                        מהלך טיפוסי:

                        קריאה ל-PEB

                        כניסה ל-PEB_LDR_DATA

                        מעבר על רשימת InMemoryOrderModuleList

                        כך מאתרים את:

                        ‎kernel32.dll‎ (כבר טעון בתהליך)

                        1. מציאת Export Table של kernel32

                        לאחר שיש BaseAddress של kernel32:

                        קריאת offset ‎e_lfanew‎ מתוך DOS header

                        קפיצה ל-NT Headers

                        גישה ל-DataDirectory → Export Table

                        חישוב כתובות:

                        AddressOfNames

                        AddressOfFunctions

                        AddressOfNameOrdinals

                        1. לולאת Hash על שמות פונקציות

                        הקוד עובר על כל שם פונקציה ב-Export Table:

                        מבנה אופייני שנראה אצלך:

                        AC
                        84 C0
                        74 07
                        C1 CA 0D
                        01 C2

                        זו לולאה שמבצעת:

                        קריאה תו-תו

                        rotate right

                        הוספת ערך

                        יצירת hash

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

                        בדרך זו מאתרים:

                        LoadLibraryA

                        GetProcAddress

                        1. טעינת user32.dll

                        אחרי שיש כתובת של LoadLibraryA:

                        הקוד קורא לה עם המחרוזת "user32"

                        מתקבלת כתובת בסיס של user32.dll

                        1. מציאת MessageBoxA

                        שוב מתבצע:

                        סריקת Export Table של user32

                        חישוב hash

                        התאמה ל-MessageBoxA

                        קבלת ה-function pointer

                        1. קריאה ל-MessageBoxA

                        ה-stack נבנה ידנית:

                        סדר הפרמטרים (stdcall):

                        push 0 ; hWnd
                        push "hello world!" ; lpText
                        push "hello world!" ; lpCaption (או דומה)
                        push 0 ; uType
                        call MessageBoxA

                        לכן מתקבלת תיבת הודעה עם הטקסט.

                        1. יציאה

                        לאחר הקריאה:

                        מתבצע ret או קריאה ל-ExitProcess (גם כן נפתר דינמית או פשוט חזרה ל-loader).

                        למה זה עובד בלי Import Table?

                        כי:

                        הכל מחושב בזמן ריצה.

                        אין תלות ב-IAT.

                        ה-Loader רק צריך למפות את ה-image ולהריץ את ה-EntryPoint.

                        מה זה בפועל?

                        PE מינימלי עם:

                        API hashing

                        Manual export resolving

                        ללא imports סטטיים

                        ללא sections מורכבות

                        זו טכניקה נפוצה בקבצים קומפקטיים מאוד וב-shellcode.

                        פירוט ממוקד לפי הרצף הבינארי ששלחת, משלב ה-EntryPoint והלאה (x86):

                        שלב 1 — כניסה וניווט ל-Export Table של kernel32

                        הרצף:

                        8B 55 3C
                        8B 54 15 78
                        01 EA

                        פירוק:

                        8B 55 3C
                        mov edx, [ebp+3Ch]
                        קריאת ‎e_lfanew‎ (offset ל-NT headers).

                        8B 54 15 78
                        mov edx, [ebp+edx+78h]
                        גישה ל-DataDirectory → Export Table.

                        01 EA
                        add edx, ebp
                        המרה מ-RVA לכתובת מוחלטת.

                        עכשיו EDX מצביע ל-IMAGE_EXPORT_DIRECTORY.

                        שלב 2 — שליפת טבלאות ה-Export

                        הרצף:

                        8B 4A 18
                        8B 5A 20
                        01 EB
                        49

                        פירוק:

                        8B 4A 18
                        mov ecx, [edx+18h]
                        NumberOfNames.

                        8B 5A 20
                        mov ebx, [edx+20h]
                        AddressOfNames (RVA).

                        01 EB
                        add ebx, ebp
                        EBX עכשיו מצביע למערך שמות.

                        49
                        dec ecx
                        התחלת לולאה.

                        שלב 3 — לולאת hash על שמות פונקציות

                        הרצף:

                        8B 34 8B
                        01 EE
                        52
                        31 C0
                        99
                        AC
                        84 C0
                        74 07
                        C1 CA 0D
                        01 C2
                        EB F4

                        פירוק לוגי:

                        8B 34 8B
                        mov esi, [ebx+ecx*4]
                        קבלת RVA של שם פונקציה.

                        01 EE
                        add esi, ebp
                        המרה לכתובת.

                        31 C0
                        xor eax,eax
                        hash = 0.

                        לולאת תווים:

                        AC → lodsb (טעינת תו)

                        84 C0 → test al,al (סוף מחרוזת?)

                        74 07 → אם 0 → יציאה

                        C1 CA 0D → ror edx,13 (rotate)

                        01 C2 → add edx,eax (עדכון hash)

                        EB F4 → חזרה ללולאה

                        זו לולאת hashing טיפוסית לזיהוי פונקציות בלי להשאיר שמות גלויים.

                        שלב 4 — התאמת hash

                        הרצף:

                        39 FA
                        5A
                        75 E5

                        39 FA → cmp edx, edi (השוואת hash לערך קשיח)

                        75 E5 → אם לא שווה → המשך לולאה

                        כאשר נמצא hash תואם → ממשיכים לשליפת הכתובת.

                        שלב 5 — שליפת כתובת פונקציה

                        הרצף:

                        8B 5A 24
                        01 EB
                        0F B7 0C 4B
                        8B 5A 1C
                        01 EB
                        03 2C 8B

                        פירוק:

                        8B 5A 24
                        AddressOfNameOrdinals

                        0F B7 0C 4B
                        movzx ecx, word [ebx+ecx*2]
                        קבלת ordinal

                        8B 5A 1C
                        AddressOfFunctions

                        03 2C 8B
                        הוספת offset של הפונקציה

                        בסיום — מתקבל pointer לפונקציה (למשל LoadLibraryA).

                        שלב 6 — קריאה ל-LoadLibraryA

                        בהמשך מופיע:

                        6A 00
                        68 30 00 40 00
                        68 0C 00 40 00
                        6A 00
                        FF D0

                        פירוק:

                        push 0

                        push offset string

                        push offset string

                        push 0

                        FF D0 → call eax

                        EAX מכיל pointer לפונקציה שנפתרה.

                        כאן נטענת "user32".

                        שלב 7 — פתרון MessageBoxA

                        אותו תהליך hash מתבצע על export table של user32.dll עד למציאת MessageBoxA.

                        שלב 8 — קריאה ל-MessageBoxA

                        Stack נבנה כך:

                        push 0
                        push "hello world!"
                        push "hello world!"
                        push 0
                        call MessageBoxA

                        ולכן מתקבלת תיבת הודעה עם המחרוזת שמופיעה בקובץ:

                        68 65 6C 6C 6F 20 77 6F 72 6C 64 21
                        מה זה בפועל?

                        אין Import Table

                        אין IAT

                        כל ה-API נפתר דינמית

                        hashing כדי להימנע משמות גלויים

                        PE מינימלי עם loader ידני

                        זו טכניקת manual export resolving מלאה.

                        פירוק מבנה ה-PE עצמו — למה ה-Loader עדיין מוכן להריץ אותו למרות שהוא מינימלי מאוד.

                        1. DOS Header

                        התחלה:

                        4D 5A ; "MZ"
                        ...
                        3C ?? ?? ?? ?? ; e_lfanew

                        4D 5A = חתימת DOS תקינה.

                        ב-offset ‎0x3C‎ נמצא ‎e_lfanew‎ — מצביע ל-NT Headers.

                        ה-DOS stub כמעט לא קיים — אבל זה לא קריטי. ה-Loader צריך רק:

                        חתימה תקינה

                        offset חוקי ל-PE

                        1. NT Headers

                        בכתובת שמצביע ‎e_lfanew‎:

                        50 45 00 00 ; "PE\0\0"
                        4C 01 ; Machine = 0x14C (x86)
                        01 00 ; NumberOfSections = 1

                        זה מספיק כדי להיחשב PE תקני ל-32 ביט.

                        1. Optional Header (PE32)

                        החתימה:

                        0B 01 ; PE32 (לא PE32+)

                        שדות קריטיים שה-Loader חייב:

                        AddressOfEntryPoint

                        ImageBase

                        SectionAlignment

                        FileAlignment

                        SizeOfImage

                        SizeOfHeaders

                        Subsystem

                        גם אם הערכים מינימליים מאוד — כל עוד הם עקביים לוגית, ה-Loader ימשיך.

                        1. DataDirectory

                        Import Directory כאן ריק או לא שמיש.

                        זה חוקי.

                        Windows לא מחייב Import Table — רק אם יש אחת, הוא יטפל בה.

                        במקרה שלך:

                        אין IAT שימושית

                        לכן אין צורך ב-relocation imports

                        הכל נעשה בקוד

                        1. Section Table

                        מוגדרת Section אחת בלבד (למשל ‎.text‎ או אפילו בלי שם משמעותי).

                        ה-Loader צריך:

                        VirtualAddress

                        VirtualSize

                        SizeOfRawData

                        PointerToRawData

                        Characteristics עם:

                        IMAGE_SCN_MEM_EXECUTE

                        IMAGE_SCN_MEM_READ

                        אם ה-Section מסומנת executable — זה מספיק.

                        1. מיפוי לזיכרון

                        בעת הרצה:

                        Windows מקצה זיכרון בגודל ‎SizeOfImage‎.

                        מעתיק את ה-Headers.

                        מעתיק את ה-Section ל-VirtualAddress.

                        קופץ ל-ImageBase + AddressOfEntryPoint.

                        אין צורך ב-IAT כי אין Imports לעבד.

                        1. למה אין צורך ב-Relocations?

                        אם:

                        ImageBase תואם למה שה-Loader מצליח להקצות
                        או

                        הקוד משתמש ב-RVA יחסיים

                        אז relocation table לא חובה.

                        ב-PE מינימליים לעיתים:

                        פשוט מניחים ImageBase סטנדרטי

                        ואם הוא פנוי — הכל עובד

                        1. למה Windows לא “דורש יותר”?

                        ה-Loader בודק מינימום:

                        חתימות תקינות

                        מבנה NT headers סביר

                        Section Table חוקית

                        EntryPoint בתוך טווח section executable

                        זהו.

                        כל השאר אופציונלי.

                        סיכום מבני

                        הקובץ שלך הוא:

                        DOS header מינימלי

                        NT headers תקינים

                        Section אחת

                        ללא Import Table

                        ללא IAT

                        ללא Relocations משמעותיות

                        EntryPoint שמבצע manual resolving

                        לכן:

                        ה-Loader עושה רק mapping → קפיצה ל-EntryPoint → ומשם הכל קורה בקוד שלך.

                        @מתכנת-חובב - כמה אחוז ממה שהוא כתב נכון?

                        נ.ב. אני הבנתי רק 3 אחוז ממה שהוא כתב, (וגם זה גוזמה)

                        מתכנת חובבמ מנותק
                        מתכנת חובבמ מנותק
                        מתכנת חובב
                        מדריכים
                        כתב נערך לאחרונה על ידי
                        #25

                        @אביגדור-ברמן בגדול נכון אבל הוא חיסר דברים
                        בכל אופן הוא כתב את זה כל כך לא ברור שלא יודע אם אני הייתי מבין את זה...
                        תעבור לג'מיני הוא הרבה יותר טוב להסביר דברים מורכבים

                        צריך עזרה בשחזור מידע? ייעוץ? egozkokus1@gmail.com

                        תגובה 1 תגובה אחרונה
                        2

                        • התחברות

                        • אין לך חשבון עדיין? הרשמה

                        • התחברו או הירשמו כדי לחפש.
                        • פוסט ראשון
                          פוסט אחרון
                        0
                        • חוקי הפורום
                        • פופולרי
                        • לא נפתר
                        • משתמשים
                        • חיפוש גוגל בפורום
                        • צור קשר