BinaryVision

Tag: Python

Reversing Python Bytecode

by on ינו.06, 2011, under כללי

מבוא

מתחיל להיות נפוץ נושא השימוש בשפות סקריפט לכתיבת קבצי EXE.
במיוחד בחברות Outsourcing שכל המטרה שלהן לכתוב מהר וקל.
אחרי שהחברה מסיימת לכתוב, מביאה מוצר, צריך להבין מה לעזאזל הם עשו שם.
Reversing קלאסי לקובץ EXE שהוא בעצם Py2EXE, לא כלכך עובד.
אז מה עושים?

מודול Dis

מחיפושים באינטרנט דבר ראשון שנתקלתי בו,
זה שיש מודול מובנה בPython להצגת הBytecode בצורה יותר ברורה, ושמו Dis.
http://docs.python.org/library/dis.html
הוא יודע לקבל code object, ולפתוח אותו למשהו קצת יותר קריא.
זה לא נותן את המקור, אבל זה מפתיע כמה זה קרוב.
בואו ננסה:

def test():
 a = 5
 b = 6
 if a == 5:
  b = 7
 return b

עכשיו נפרק את זה בעזרת Dis

>>> import dis
>>> dis.dis(test.func_code)
 2           0 LOAD_CONST               1 (5)
           3 STORE_FAST               0 (a)

 3           6 LOAD_CONST               2 (6)
           9 STORE_FAST               1 (b)

 4          12 LOAD_FAST                0 (a)
          15 LOAD_CONST               1 (5)
          18 COMPARE_OP               2 (==)
          21 JUMP_IF_FALSE           10 (to 34)
          24 POP_TOP

 5          25 LOAD_CONST               3 (7)
          28 STORE_FAST               1 (b)
          31 JUMP_FORWARD             1 (to 35)
      >>   34 POP_TOP

 6     >>   35 LOAD_FAST                1 (b)
          38 RETURN_VALUE

זה מדהים עד כמה זה מדוייק, כולל שמות משתנים והכל.
המספר הראשון זה מספר השורה בקוד מקור…
המספר שמופיע לפני כל מילה זה מספר הByte
המילה, זה הפעולה (לדוגמה LOAD_CONST)
המספר אחריה זה פרמטר, ובסוגריים זה הפיכת הפרמטר למשהו משמעותי אם אפשר.

נעבור לפי הסדר, ונראה כמה קל זה לבנות חזרה את הקוד:
שורה 2, LOAD_CONST טוען קבוע למחסנית, הקבוע הוא באינדקס 1, אבל הערך שלו הוא 5.
ואז STORE_FAST שומר את הערך מהמחסנית לתוך המשתנה באינדקס 0, ששמו a.
מה כל פעולה עושה מתועד היטב בקישור למודול DIS, ומה שנשאר זה להבין שהפקודה היא:

a = 5

שורה 3, אותו דבר, נעבור לשורה 4.
טוענים את a למחסנית, טוענים 5, ועושים COMPARE_OP עם ==.
הפעולה משווה בין השניים האחרונים במחסנית במחזירה את התשובה למחסנית.
עד כה יש לנו a == 5.
JUMP_IF_FALSE בודק את הערך האחרון במחסנית, ואם הוא FALSE קובץ לByte 34.
POP_TOP שולף את הערך האחרון במחסנית.
אז אם נרצה לשחזר את זה, צריך להבין שבמקרה שהערך הוא שקר, הוא מדלג _מעל_ קטע הקוד הבא, ז"א אם נרצה לרשום את זה רצוף, אז במקרה של אמת, הוא נכנס לקטע קוד, אז התנאי נראה כך:

 if a == 5:
     #... continue here ...
 #... if false jump to here ...

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

py2exe

הייצור שקוראים לו py2exe אורז את סקריפט הPython, כל ספריות, וכל דבר שצריך כדי להריץ אותן, לתוך EXE אחד.
והוא עוזה את זה בצורה הבאה:
כל הDLLים, וכל הספריות שעושים להן Import, הוא מקמפל לBytecode, ושם בZIP, בתוך הEXE.
ניתן לחלץ אותו ממש בקלות ע"י 7Zip שמאתר אותו, ופשוט נותן להוציא מתוכו קבצים.
עכשיו צריך, רק למצוא את הסקריפט הראשי.
הוא נשמר כResource בEXE, אפשר בקלות לשלוף אותו עם Visual Studio.
פותחים EXE עם התוכנה, והוא מציג את כל הResources, אחד מהם זה הקוד המקומפל.

רק משהו קטן

קובץ .pyc משוייך לPython שאיתו בנו אותו, וזה לא סתם, כי הBytecode משתנה.
כל הקבצים שנמצאים בZIP ניתן לעשות להן import כל עוד הגרסה של הפייטון תואמת,
ואחרי זה אפשר להריץ dis.dis על המודול כולו. (אפשר גם על פונקציות בנפרד).
עם הResource העניין קצת יותר בעייתי, כי הוא לא בדיוק Library, אלא Marshalled, בעזרת מודול marshal.
בשימוש במודול אפשר לשלוף את הCode Object הראשי, וממנו למצוא כל Code Object אחר, ולהעביר אותו לDIS גם כן.

פרויקט

חשבתי לעשות Python Decompiler,
זה מתחיל להיות קשה כשמגיעים לתנאים מסובכים, ולולאות עם תנאים מסובכים בתוכן.
אני חושב שזה אפשרי לחזור לקוד מקור בצורה אוטומטית, מה דעתכם?
(יש כמה נסיונות לDecompiler באינארנט, לא ראיתי אחד נורמלי…)

6 Comments :, , , more...

אתגר Hacking של Offensive Security – שלב שני

by on יול.06, 2010, under כללי

מה היה לנו

  • קיבלתי Root על 192.168.6.200
  • מצאתי עליו קובץ mosquito.exe

http://www.filesonic.com/file/2125504394/mosquito.exe
מי שרוצה לנסות קצת בעצמו מוזמן להוריד את הקובץ אליו, ולהפסיק לקרוא כאן.

mosquito

בוא ננחש מה עושה הקובץ לפי הImports שלו.

Mosquito Imports

משתמש בסוקטים, וקצת Threads פה ושם, חוץ מזה כל מיני דברים מציקים כמו IsDebuggerPresent.
אז אם נריץ אותו, והוא מאזין על פורט, נוכל בקלות לראות איזה.
הרצתי אותו, קפץ הFirewall ואומר שהוא מנסה להאזין על 4597, אישרתי לו.
טוב, ננסה להתחבר אליו עם Netcat ולראות אם הוא זורק לנו משהו למסך.

nc -nvv 127.0.0.1 4597

קופץ הFirewall, ואומר לי שהmosquito.exe מנסה ליצור חיבור ל127.0.0.1 לפורט 1080…. מאיפה זה בא??
החלטתי שלפני שאני קופץ פנימה לתוך הקוד, אני מרים Netcat מאזין מקומי, על פורט 1080, ורואה מה הולך שם.

nc -nvvLp 1080

מריץ את הייתוש מחדש, מתחבר אליו, רואה שהוא מתחבר לnetcat השני, וכלום לא קורה…
שולח קצת טקסט, לא קורה כלום…..
טוב, בדיקה אחרונה לפני שצוללים לקוד, האם הוא פותח חיבור תמיד ל127.0.0.1? או שזה חיבור חזרה למי שניסה להתחבר אליו?
נבדק בצורה פשוטה ע"י מכונה שהיא לא מקומית, כתובת P) אחרת שמנסה להתחבר לMosquito, ואיזה יופי, הFirewall אומר שהוא עדיין מנסה להוציא חיבור ל127.0.0.1 למרות שהחיבור הגיע מכתובת אחרת.

צוללים לקוד

פותח IDA חזרה, מאתר את המקום שבו יש קריאה לrecv.
מריץ Netcat מקומי מאזין על 1080.
פותח ollydbg, מציב breakpoint על הRecv.
פותח Netcat נוסף ומתחבר לmosquito שמריץ הollydbg.
קופץ הBreakpoint, אני שולח איזה שטות בNetcat, ומתחיל לעקוב אחרי זה בקוד בollydbg שורה שורה.
אני לא הולך לפרט את כל התהליך, אבל זה המסקנות שהגעתי אליהן אחרי כמה ריצות:

  • כל חבילה שמתקבלת עוברת איזה "הצפנה" פשוטה… XOR עם הערך 4.
  • נבדק האם האם הכתובת המקומית של השרת היא 192.168.6.141
  • המידע נשלח לסוקט השני ששמחובר מקומית לפורט 1080

אז מה עכשיו

  • חיפוש חולשות בקוד עצמו ובטיפול של הBuffer מהנקודה שהתקבל ועד שנשלח הלאה.

לא מצאתי חולשות רגילות של Buffer Overflow

  • אולי זה לא אתגר ניצול חולשה, אלא צופן\Reverse? אולי צריך לשלוח מחרוזת מיוחדת כך שאחרי ההצפנה זה יהיה איזה מפתח.

נזכרתי בטקסט שהיה רשום באתר של Mosquito, עם התמונה, היה כתוב "bRAin suck3r".
בגלל איך שזה היה כתוב, חשבתי שזאת המחרוזת שמי שזה לא יהיה בפורט 1080 צריך לקבל.
כתבתי סקריפט שמקסר עם 4 ושולח לכתובת שאני מבקש, הרצתי, ולא קיבלתי תשובה.

  • רגעעעעע, הדבר הזה בכלל מחזיר תשובות מאותו שירות שרץ על 1080?

בבדיקה מקומית (שליחה בNetcat המאזין על 1080) מתקבל אותו זבל "מוצפן" בNetcat המתחבר.

  • אז אם זה הצפנה דו כיוונית, אולי זה פרוקסי טיפש מול שירות רגיל כלשהו?

מה רץ בדרך כלל על 1080? HTTP…
שיניתי את הסקריפט כך שישלח בקשת GET מקוסרת ב4, ויציג לי תשובה אם יש.
קיבלתי הרבה הרבה זבל חזרה.
הוספתי גם קיסור ב4 על התשובה, וקבילתי דף HTML.

  • אז הדבר הזה הוא פרוקסי לשרת WEB

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

#!/usr/bin/python
#
import socket
import sys
import thread

def tunnel_data(sock1,sock2):
	try:
		data = sock1.recv(0xffff)
		while data:
			ndata = ""
			for i in data:
				ndata += chr(ord(i) ^ 4)
			sock2.sendall(ndata)
			data = sock1.recv(0xffff)
		sock2.close()
	except Exception,e:
		print e
		sock1.close()
		sock2.close()

def main(ip,lport):
	global MSG
	lsock = socket.socket()
	lsock.bind(("0.0.0.0",lport))
	lsock.listen(1)
	while True:
		cli = lsock.accept()[0]
		rsock = socket.socket()
		rsock.connect((ip,4597))
		thread.start_new_thread(tunnel_data,(cli,rsock))
		thread.start_new_thread(tunnel_data,(rsock,cli))

main(sys.argv[1],long(sys.argv[2]))

האתר

נפתח חלון של איזה תוכנת צ'אט, שקוראים לה Easy Chat Server.
בנוי בAJAX, ומעוצב בצורה שמאד מסכנת את הפיצה שאכלתי לא מזמן.

Easy Chat Server

התחלתי לשחק איתו, לחפש SQL Injections, לחפש בעיות הרשאות, לנחש סיסמה של המנהל של הערוץ.
שזה לא היה קשה, הסיסמה של המנהל admin הייתה admin, אבל זה לא נתן לי כלום.
טוב, אולי זה שרת מוכר באינטרנט, אולי יש לו חולשות.
איזה יופי שבדף תוצאות הראשון אני מוצא את הקישור הבא:
http://www.metasploit.com/modules/exploit/windows/http/efs_easychatserver_username

פריצה מעל פרוקסי מצפין

הפעלתי Metasploit הגדרתי את הפרצה שתנסה לפרוץ לי את הפרוקסי המקומי, ותשתמש בMeterpreter שמתחבר חזרה אלי ישירות.
הרצתי את הפרצה, ואחרי כמה ניסיונות כושלים, זה עבד!!
קיבלתי Shell על השרת 192.168.6.141.
בדיקה מהירה גילתה שאני משתמש חסר הרשאות, שאין לו גישה לDesktop של הAdministrator.
וGetSystem של Meterpreter לא עזר.
מערכת ההפעלה היא Windows 2003 SP2.

נסיונות לעלות הרשאות

ציינתי כבר שכל 30 דקות המכונות עוברות Revert?
האם אמרתי עד כמה מעצבן זה כשאתה מנסה למצוא איך לעלות הרשאות במכונה שיש לך גישה אליה?
הייתי צריך לפרוץ מחדש את המכונה כל פעם שאיבדתי גישה בגלל הRevert.
אבל מספיק לבכות, כאן זה הזמן לאמר שלעלות הרשאות במכונה לא הצלחתי באותן 10 שעות שהיה לי לאתגר הזה.
דברים שניסיתי:

  • מציאת חולשות Privilege Escalation ידועות למערכת ההפעלה, לא הלך, המכונה כנראה Fully Patched
  • מציאת Services שרצים כSystem לבדוק אם אפשר להחליף להם את הEXE ולעשות להפיל אחד מהם שיעלה מחדש, היה שם שרת VOIP שרץ כSystem ומאד קרץ לי, אבל שרף את רוב הזמן.
  • חיפוש קבצים זרוקים במערכת שיש לי גישה "בטעות" אליהם ויש שם סיסמה או משהו שיעזור

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

8 Comments :, , , , , more...

פיתוח Mokonnect

by on יונ.05, 2009, under כללי

מבוא

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

קווים מנחים

כמובן שלא מתחילים לכתוב תוכנה בלי שיודעים איזה בעיות היא צריכה לפתור, ואיזה אפשרויות צריך שיהיה לה…

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

Mockup

תמונות שציירתי עוד לפני שהתחלתי לפתח (כדי לראות איך זה יראה, ואם זה נוח לשימוש):

מסך ראשי

מסך ראשי


רשת USB

רשת USB


Wifi

Wifi


ניתוב

ניתוב

שיטות שימוש

התחברות לרשת אלחוטית פעם אחת

פותחים את התוכנה, לוחצים על Wifi, מכוונים את ההגדרות, לוחצים על Apply, מחכים שהוא יתחבר ויציג פלט, ויוצאים מהתוכנה

התחברות לרשת אלחוטית יותר מפעם אחת

פותחים את התוכנה, לוחצים על Wifi, מכוונים את ההגדרות, לוחצים על Apply, מחכים שהוא יתחבר ויציג פלט, בתפרטי הראשי מסמנים את Wifi, ולוחצים על Save Profile, כותבים את שם הפרופיל ותיאור קצר, שומרים ויוצאים.
בפעם הבאה שנכנסים ורוצים להתחבר לאותה רשת, לוחצים פשוט על Select Profile בוחרים את שם הפרופיל וזה עושה הכל לבד.

התחברות לGPRS וניתוב האינטרט לחיבור USB

פותחים את התוכנה, מגדירים את החיבור USB, לוחצים Apply, כנ"ל גם החיבור GPRS, לוחצים Apply,
הולכים לRoute, מגדירים שם מי החיבור הראשי, מאיפה לוקחים DNS, ומי נמצא בNAT וכאלה, לוחצים Apply,
בתפריט הראשי שומרים את הפרופיל, ופעם הבאה ההגדרות האלה יהיו במרחק בחירת פרופיל מתוך רשימה.

סביבת פיתוח

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

סביבת הפיתוח

סביבת הפיתוח

  • VMWare Workstation – כי זה מהיר מאד בWindows, ונוח…
  • Slackware 12.2 – אם יש כלי פיתוח כלשהו שצריך ומשתמשים בו בעולם, אז הוא קיים בהתקנה הבסיסית של Slackware.

דברים שהתקנתי ובעיות שפתרתי:

  • Enlightment DR17 – החדש שהמוקו מריץ (בעזרת סרקריפט easy_e17.sh שלוקח לו שנים לרוץ)
  • Illume-SHR Profile – ערכת נושא והגדרות לillume (מתוך הGIT של הפרוייקט)
  • הגדרת DPI נכונה – ההגדרה צריכה להיות פי 2 יותר קטנה מהDPI הנוכחי. (בתוך הX11 כבר)
  • e17 Python Bindings – אני רוצה לבנות את התוכנה בPython (מתוך המקור של e17)

עכשיו יש לי סביבת פיתוח שמדמה איך הדברים יראו ובערך יעבדו המוקו.

התקדמות

תמונת מסך: מסך ראשי

תמונת מסך: מסך ראשי


מי שרוצה לראות את הקוד בצורה יפה: http://code.assembla.com/shrdev/subversion/nodes/Mokonnect/trunk
קישור לSVN למי שרוצה: http://subversion.assembla.com/svn/shrdev/Mokonnect/trunk
כפי ששמתם לב אני משתמש בAssembla לצרכי שמירת הקוד שלי, ואולי גם אשתמש בWiki שם לצורך תיעוד.
בכל מקרה המצב של הקוד כרגע לא משהו.
יש GUI, בערך קרוב למה שתכננתי, ויש גם את ההגדרות של USB Network,
כל השאר לא פעיל בינתיים.
בתוך ההגדרות של USB Network, אני נלחם עם Apply בצורה חכמה,
תמונת מסך: USB

תמונת מסך: USB


כך שבזמן שאני עושה פעולות הוא לא יתקע את הGUI ויעדכן אותו עם הודעות התקדמות.
זה יותר קשה משציפיתי בגלל שהToolkit לא תומך בThreads יותר מדי.
בכל מקרה, עד כאן להיום.

תשאירו תגובות, הערות, הצעות לשיפור, או בכלל אם יש לכם משהו להגיד.

9 Comments :, , , , more...

מחפש משהו?

תשתמש בטופס למטה כדי לחפש באתר: