שְׁאֵלָה:
קובץ דחוס הנדסי לאחור, מאיפה להתחיל?
Harriv
2013-06-15 20:45:42 UTC
view on stackexchange narkive permalink

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

הקובץ נמצא כאן: http://www.bittilahde.fi/Tietokanta.dat (Database.dat באנגלית)

תוכנית ניהול הספרים נמצאת כאן: http://www.pesistulokset.fi/Kirjaus504.exe

מה שגיליתי :

  • ההיסטוגרמה של קובץ מסד הנתונים שטוחה לחלוטין
  • אין כותרת שיכולתי לזהות בקובץ מסד הנתונים
  • ה- exe נערך עם דלפי 4
  • אני יכול למצוא כמה מבני נתונים עם IDR, אך לא מצליח להבין עד כמה לא דחוס את הקובץ.

מה יכול להיות הצעד הבא?

ניסית binwalk?
@bueno לא, אני חדש בזה אז מעולם לא שמעתי על זה. האם אתה מנח את זה: http://code.google.com/p/binwalk/
כן, הוא סורק את הקובץ ומחפש כל מיני סוגי קבצים שונים. זה דורש פיתון וליבמגי, אני חושב. זה דברים טובים.
@bueno נראה כמו תוכנית נהדרת, אבל במקרה זה זה לא אומר לי שום דבר שימושי. גרף האנטרופיה נותן 1.0 שטוח לכל הקובץ.
הוספתי את binwalk כתשובה, כי זה עשוי לעזור לאנשים אחרים שיש להם שאלה דומה. מידע נוסף על גרף דחיסה אנטרופיה ניתן למצוא כאן: http://www.devttys0.com/2013/06/differentiate-encryption-from-compression-using-math/
ארבע תשובות:
Runium
2013-07-02 13:38:10 UTC
view on stackexchange narkive permalink

כשמסתכלים על זה ב OllyDbg זה נראה כמו משימה כבדה. נראה כמו מסד נתונים מותאם אישית עם נתונים מוצפנים ו (מותאמים אישית?) דחוסים. בדרך כלל זה או כזה יהיה המקרה ביישומים כאלה. קובץ שטוח עם נתונים מובנים אינו חלק מקובץ זה.

בכל מקרה. בתור התחלה:

בדיקה מהירה לאחר ניסיון של כמה כלי דחיסה כלליים כמו 7z או binwalk, (לא בדקתי זאת), יכולה להיות שימוש ב ProcMon מ- Sysinternals. הפעל את ProcMon, לאחר מכן את היישום שלך והגדר מסנן ליישום ב- ProcMon. אתה מגלה במהירות:

בקיצור הוא קורא בנתחים בגודל משתנה, אך לצורך עיבוד נתונים ראשי הוא קורא נתחים של 16384 בתים. התהליך בשלבים:

  1. צור מפת זרע של 256 מספרים שלמים. (בוצע פעם אחת בהתחלת היישום.)
  2. לולאה:
    2.1 קרא 16384 בתים למאגר מקובץ .dat.
    2.2 שגרת XOR במאגר באמצעות אופסט וארבעה בתים אחרונים של מאגר כ בסיס.
    2.3 סכום בדיקה במאגר XOR'ed באמצעות מפת זרעים משלב 1.
    2.4 ניתוח מאגר וקריאת נתונים.
  3. o>

    היישום קורא גם את אותם נתחים מרובים פעמים.


    2.1:

    דוגמה :

    013D0010 D4 9E BE BF 1C 1C 0B D4 C5 E7 11 B5 09 48 87 FA Ôž¾¿ÔÅçµ.H ‡ ú013D0020 29 4C 03 C9 DE 4A 2B 71 74 7F D2 48 E7 13 94 4E) LÉÞJ + qtÒHç ”N ... 013D3FF0 6A D1 55 92 E2 16 60 53 69 89 86 7D D9 D8 10 BC jÑU'â`Si ‰ †} Ùؼ013D4000 90 F3 D1 48 28 47 34 EC 39 36 EC 4D 69 2A 7D E5 óÑH (G4ì96ìMi *} å | _____._____ | | DWORD אחרון aka בדיקת - +   מראש> 

    שלבים ופרטים לפי סדר הגילוי:

    פצל את קובץ ה- .dat בגושים של 16384 בתים וצור גם dump hex של כל קובץ לחיפוש והשוואה קלים. למען האמת, אני משתמש בלינוקס בחלק זה עם dd , xxd -ps , grep , diff וכו '

    התחל את OllyDbg, פתח את היישום, אתר CreateFile והגדר נקודת פריצה:

      00401220 $ -FF25 18825000 JMP DWORD PTR DS: [<&kernel32.CreateFileA>; kernel32.CreateFileA  

    לחץ על F9 עד ששם הקובץ (ב- EAX ) הוא קובץ .dat. הגדר / הפעל נקודת שבירה ב- ReadFile . F9 וכאשר הקריאה נעשית התחל לדרוך ולבדוק מה נעשה.


    מסתכל על זה:

    2.2:

    לאחר קריאה זה שנה תחילה את המאגר על ידי שימוש בקיזוז כ"קסם "החל מ:

      0045F5EC / $ 53 PUSH EBX; ALGO 2: אלגוריתם XOR - הקובץ פוסט נקרא .... 0045F6B6 \. C3 RETN; ALGO 2: RETN  

    לפחות שניים מהפעולות שבוצעו נראות libj_randl1 () ו- libj_randl2 (). (זה יהיה שלב 2.2 ברשימה לעיל.)

    פשוט:

      edx = כתובת זיכרון של bufferecx = קיזוז / 0x4000edi = edxebx = ecx * 0x9b9esi = dword אחרון למאגר & 0x7fffffffecx = 0i = 0; while (i < 0x3ffc) {/ * גודל המאגר - 4 * / מניפולציה במאגר}  

    כל השגרה מתורגמת ל- קוד C:

      int xor_buf (uint8_t * buf, offset long, long buf_size) {int32_t eax; int32_t שפל; int32_t esi; ארוך אני; buf_size - = 4; ebx = (אופסט / 0x4000) * 0x9b9; / * אינטל int 32 * / esi = ((buf [buf_size + 3] << 24) | (buf [buf_size + 2] << 16) | (buf [buf_size + 1] << 8) | buf [0] & 0x7fffffff; עבור (i = 0; i < buf_size / * 0x3ffc * /; ++ i) {/ * libj_randl2 (sn) Ref. קישור למעלה. * / ebx = ((ebx% 0x0d1a4) * 0x9c4e) - ((ebx / 0x0d1a4) * 0x2fb3); אם (ebx < 0) {ebx + = 0x7fffffab; } / * libj_randl1 (sn) Ref. קישור למעלה. * / esi = ((esi% 0x0ce26) * 0x9ef4) - ((esi / 0x0ce26) * 0x0ecf);
    אם (esi < 0) {esi + = 0x7fffff07; } eax = ebx - 0x7fffffab + esi; אם (eax < 1) {eax + = 0x7fffffaa; } / * שנה שלושה בתים הבאים. * / buf [i] ^ = (eax >> 0x03) & 0xff; אם (++ i < = buf_size) {buf [i] ^ = (eax >> 0x0d) & 0xff; } אם (++ i < = buf_size) {buf [i] ^ = (eax >> 0x17) & 0xff; }} להחזיר 0;}  

    ואז נוצר בדיקת בדיקה של המאגר שהתקבל, (פחות dword אחרון), ונבדק מול dword האחרון. כאן הוא משתמש במאגר מפלח BSS שנוצר בעת ההפעלה, שלב 1. מהרשימה למעלה . (קיזוז 0x00505000 + 0x894 ושימוש באזור של 4 * 0x100 כיוון שהוא 256 שלמים של 32 סיביות). נראה כי מפת זרעים זו קבועה (לעולם לא נוצרה / שונתה מחדש) וניתן לדלג עליה אם לא רוצים לאמת את המאגר.

    1.

    נקודת קוד בפירוק ( הערות שלי.):

      0045E614. 53 דחף EBX; ALGO 1: יצירת צ'קסום MAGICK BSS ... 0045E672. C3 RETN; ALGO 1: RETN  

    ניתן לפשט את הקוד למספרי BSS ב C כמו למשל :

    int eax; / * INT NR 1, המספר הבא שנוצר לשמירה * / int i, j; int bss לא חתום [0x100] = {0}; / * קיזוז 00505894 * / עבור (i = 0; i < 0x100; ++ i) {eax = i << 0x18; עבור (j = 0; j < 8; ++ j) {if (eax & 0x80000000) {eax = (eax + eax) ^ 0x4c11db7; } אחר {eax << = 1; }} bss [i] = eax;}  

    2.3:

    כי מערך ה- bss int משמש במאגר המנוהל ליצירת בדיקת בדיקה שאמורה להיות שווה למספר השלם האחרון בתאים 16384 שנקראו מהקובץ. (dword אחרון, זה שדילג עליו בשגרה ובדיקת XOR'ing.) . זה יהיה שלב 2.3 ברשימה שלמעלה.

      char לא חתום * buf = מאגר קבצים מניפולטיבי; char לא חתום * bss = זיכרון dump 0x00505894 - 0x00505C90, או מהקוד לעיל = 0x13d0010; / * מיקום זיכרון למאגר. * / edx = 0x3ffc; / * גודל המאגר - 4 בתים (בדיקת בדיקה). * / ...  

    ביציאה ecx שווה לסכום הבדיקה.

    נקודת קוד בפירוק (הערות שלי.):

      0045E5A8 / $ 53 PUSH EBX; אלגו 3: חישוב צ'קסום לאחר אלגוריתם 2 ... 0045E5E0 \. C3 RETN; ALGO 3: RETN (EAX = CHECKSUM == BUFFER LAST 4 BYTES)  

    מקוצר לשגרת C זה יכול להיות משהו כמו:

      int32_t checksum ( מפה int32_t [0x100], uint8_t * buf, long len) {int i; int32_t k, cs = 0; עבור (i = 0; i < len; ++ i) {k = (cs >> 0x18) & 0xff; cs = map [buf [i] ^ k] ^ (cs << 0x08); } להחזיר cs;}  

    זה מסומן כדי להיות בסדר ואז סכום הבדיקה במאגר מוגדר כ: שני בתים פחות משמעותיים = 0, שני בתים משמעותיים ביותר מוגדרים לחלק מספר (מספר נתח בקובץ או מספר קריאה, (החל מ- 0)).

      0045F9BF. C680 FC3F0000 >MOV BYTE PTR DS: [EAX + 3FFC], 0; הגדר שני בתים נמוכים יותר של בדיקת בדיקה ב- dat buf ל 00045F9C6. C680 FD3F0000 >MOV BYTE PTR DS: [EAX + 3FFD], 0; עוקב אחר הקודם 0045F9CD. 66: 8B4D F8 MOV CX, WORD PTR SS: [EBP-8]; הגדר את CX כדי לערום את ערך המצביע של addr EBP - 8 (מונה מסוג) 0045F9D1. 66: 8988 FE3F00>MOV WORD PTR DS: [EAX + 3FFE], CX; הגדר מאגר .dat בתים גבוהים יותר כמו CX.  

    כעת אחרי שכל זה נעשה ההעתקה בפועל של נתונים מתחילה באלגוריתמים עוד יותר. כאן העבודה האמיתית מתחילה . זיהוי סוגי נתונים, מבנים, איפה ומה וכו 'מצא כמה שגרות שחילצו שמות וכו'. אבל כל מה שהוא פיני לא עזר להקל על האחיזה;).

    הנתונים שלמעלה יכולים להיות התחלה.

    כמה נקודות פריצה שעשויות לעניין מלכתחילה:

      Breakpoints Address Module פירוק פעיל תגובה 0045E5A8 Kirjaus5 מושבת PUSH EBX ALGO 3: חישוב בדיקת סכום לאחר אלגוריתם 20045E5E0 Kirjaus5 מושבת RETN ALGO 3: RETN (EAX = CHECKSUM == BUFFER Last 4 BYTES) 0045E614 Kirjaus5 Disabled PUSH EBX ALGO 1: CHERKSUMMER MAGIC BSS0045E672 Kirjaus5 Disabled RAG ALFO קרא ALGORITHM0045F6B6 Kirjaus5 מושבת RETN ALGO 2: RETN  

    כמה הערות:

    שמור גיבוי של קובץ ה- .dat עובדים עם. אם תבטלו את היישום, הקובץ לעיתים נפגם מכיוון שהוא, כפי שצוין על ידי @blabb, כתבו נתונים חזרה לקובץ. נראה שגם קובץ ה- dat הוא חי ולכן הורדה חדשה שלו תביא לנתונים שונים.

שאלה אחת: איך יצרת את קטעי קוד C אלה? ביד או באמצעות כמה כלים?
@Harriv: ביד. דרך אחת, כאשר השגרה לא ארוכה, יכולה להיות ליצור משתנה לכל רשום (בשימוש) וכו 'וכמעט להכין שרטוט ב- C, אז אתה רואה מה זה ויכול לעשות ממנו פונקציות ולולאות. לאחר זמן מה ועם פעילות גופנית, קל יותר לזהות מה מה ואיך לכתוב את זה יותר קומפקטי בפעם הראשונה ...
blabb
2013-06-16 12:33:39 UTC
view on stackexchange narkive permalink

קובץ ה- .dat שפרסמת נכתב בחזרה בכל פעם שהוא ניגש לאפליקציה שלך בגודל קבוע של 9.6 מגהבייט (0x267 * 0x4000) = 0x99c0000 בתים

4000 בתים ניגשים בכל קריאה עוקבת 267 פעמים ReadFile האם Doneeach מבין 4000 הבתים הוא xorred באמצעות שגרה (מותאם אישית ??) ואז בדוק את הסיכום עבור (int i = 0; i< 0x267; i ++) {checksum = * (DWORD *) (FilePointer) (0x3ffc + i )} אז בקובץ דאט מת שנפתח באמצעות hexeditor ה- dwords 0x3ffc, 0x7ffc ...... מכיל את בדיקת הבדיקה האחרונה

יתכן שתצטרכו להנדס את שגרת ה- xorring ואת שגרת הבדיקה

לנתח את כל ערימות הקריאות בקובץ היומן שנוצר על ידי windbg עם נקודת הפסקה זו

C: \ >cdb -c ".logopen kir.txt; bu ntdll! NtReadFile \" .if (poi (esp + 0x1c)! = 0x4000) {gc} .else {kb; g} \ "" Kirjaus504.exe

נהדר, תודה. פשוט הנחתי שזה דחוס ..
shebaw
2013-06-16 10:18:56 UTC
view on stackexchange narkive permalink

ובכן מנקודה זו ואילך, הפתרון הטוב ביותר שלך יהיה להפוך את פונקציות טעינת מסדי הנתונים של התוכנית מכיוון שמאגר המידע עשוי להיות מותאם אישית. הצב נקודת הפסקה בממשקי ה- API של CreateFile / OpenFile כאשר הוא טוען את מסד הנתונים ואז חפש את פונקציות המניפולציה במסד הנתונים כדי לראות כיצד הוא מחלץ את התוכן. לא ניתן לנסות זאת בתוכנית שפרסמת מאחר וממשק המשתמש הוא בפינית.

samuirai
2013-06-19 18:36:14 UTC
view on stackexchange narkive permalink

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



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