Go: Compilación Cruzada y UPX

CiberSeguridad 22 de feb. de 2024

GO. Un único código para distintos S.O.

Varias de las ventajas que tiene el lenguaje de programación Go (Golang) son:

  • Es Open Source
  • Sintaxis muy parecida a C
  • Afín a Phyton, en cuanto a su facilidad de uso
  • Es "Staticaly Type" lo cual permite rendimiento optimo en compilación
  • La compilación genera directamente código máquina
  • Permite con un único código generar binarios para Linux, Windows ó Mac

UPX: Ultimate Packer for eXecutables

UPX es un empaquetador de ejecutables gratuito, portable y de alto rendimiento, con funciones de protector de software.
UPX soporta (y autodetecta) diferentes formatos de ejecutables, permite comprimir binarios de distintas arquitecturas y versiones de Sistemas Operativos (ya sean actuales o antiguos) y ejecutarlos directamente en el destino en memoria.

Actualmente soporta:

    amd64-darwin.dylib                   dylib/amd64
    amd64-darwin.macho                   macho/amd64
    amd64-linux.elf                      linux/amd64
    amd64-linux.kernel.vmlinux           vmlinux/amd64
    amd64-win64.pe                       win64/pe
    arm-darwin.macho                     macho/arm
    arm-linux.elf                        linux/arm
    arm-linux.kernel.vmlinux             vmlinux/arm
    arm-linux.kernel.vmlinuz             vmlinuz/arm
    arm-wince.pe                         wince/arm
    arm64-darwin.macho                   macho/arm64
    arm64-linux.elf                      linux/arm64
    armeb-linux.elf                      linux/armeb
    armeb-linux.kernel.vmlinux           vmlinux/armeb
    fat-darwin.macho                     macho/fat
    i086-dos16.com                       dos/com
    i086-dos16.exe                       dos/exe
    i086-dos16.sys                       dos/sys
    i386-bsd.elf.execve                  bsd.exec/i386
    i386-darwin.macho                    macho/i386
    i386-dos32.djgpp2.coff               djgpp2/coff
    i386-dos32.tmt.adam                  tmt/adam
    i386-dos32.watcom.le                 watcom/le
    i386-freebsd.elf                     freebsd/i386
    i386-linux.elf                       linux/i386
    i386-linux.elf.execve                linux.exec/i386
    i386-linux.elf.shell                 linux.sh/i386
    i386-linux.kernel.bvmlinuz           bvmlinuz/i386
    i386-linux.kernel.vmlinux            vmlinux/i386
    i386-linux.kernel.vmlinuz            vmlinuz/i386
    i386-netbsd.elf                      netbsd/i386
    i386-openbsd.elf                     openbsd/i386
    i386-win32.pe                        win32/pe
    m68k-atari.tos                       atari/tos
    mips-linux.elf                       linux/mips
    mipsel-linux.elf                     linux/mipsel
    mipsel.r3000-ps1                     ps1/exe
    powerpc-darwin.macho                 macho/ppc32
    powerpc-linux.elf                    linux/ppc32
    powerpc-linux.kernel.vmlinux         vmlinux/ppc32
    powerpc64-linux.elf                  linux/ppc64
    powerpc64le-linux.elf                linux/ppc64le
    powerpc64le-linux.kernel.vmlinux     vmlinux/ppc64le

Instalación rápida de Go

El artículo actual no es un tutorial de Go, pero vamos a realizar una instalación en Debian 12 y una configuración rápida de Go para poder trabajar con él.

Salimos a nuestra terminal y escribimos:

# Actualizamos SO
sudo apt update; sudo apt -y upgrade

# Instalamos Go (Golang)
sudo apt -y install golang-go

# Ajustamos variables de compilación para nuestro usuario
echo 'export GOOS=linux GOARCH=amd64' >> ~/.bashrc

Cierra el terminal y vuelve a abrirlo para que tengas cargadas las variables GOOS y GOARCH y comprueba la versión de Go:

# Comprobar variables compilacion
env|grep '^GO'
 GOARCH=amd64
 GOOS=linux
 
# Comprobar version de Go
go version
  go version go1.19.8 linux/amd64

Enlace a la documentación de Go:

Documentation - The Go Programming Language
https://go.dev/doc/

Instalación rápida de UPX

Vamos a instalar el binario de UPX que nos permite comprimir binarios, de nuevo desde la terminal ejecuta lo siguiente:

# Descargar ultima version de UPX
wget https://github.com/upx/upx/releases/download/v4.2.2/upx-4.2.2-amd64_linux.tar.xz -O /tmp/upx.tar.xz

# Descomprimir UPX (e instalar en la ruta)
cd /tmp
tar -Jxvf  upx.tar.xz
sudo cp upx /usr/local/bin/

# Comprobar version de UPX
upx --version
  upx 4.2.2
  NRV data compression library 0.84
  UCL data compression library 1.03
  zlib data compression library 1.3.0.1-motley
  LZMA SDK version 4.43
  Copyright (C) 1996-2024 Markus Franz Xaver Johannes Oberhumer
  Copyright (C) 1996-2024 Laszlo Molnar
  Copyright (C) 2000-2024 John F. Reiser
  Copyright (C) 2002-2024 Jens Medoch
  Copyright (C) 1995-2023 Jean-loup Gailly and Mark Adler
  Copyright (C) 1999-2006 Igor Pavlov
  UPX comes with ABSOLUTELY NO WARRANTY; 
  for details type 'upx -L'.omprobar UPX

Enlace a la web de UPX:

UPX: the Ultimate Packer for eXecutables - Homepage
UPX homepage: the Ultimate Packer for eXecutables
https://upx.github.io/

Jugando con "virus" y "payloads"

Evidentemente no vamos a usar virus, ni ningún tipo de payload real, se trata de un simple ejercicio para un primer acercamiento sencillo para ver que tipo de evasiones se pueden realizar al usar ciertos lenguajes modernos y la posibilidad de descubrimiento de "cargas malignas" en software.

Para las pruebas vamos a usar Eicar Test File, se trata de una cadena de texto oficial que se usa para la comprobación básica del funcionamiento de los antivirus.

Web oficial de descarga de ficheros con Eicar Test File:
https://www.eicar.org/download-anti-malware-testfile/

Nos descargamos el fichero TXT del fichero Eicar para poder usar su contenido en el código que vamos a generar, lo llamamos eicar.txt

Contenido del fichero Eicar

Creando aplicación en Go

Vamos a crear un pequeño programa, al que vamos a llamar "virus", que compilaremos para Linux, Windows y MacOs, en el que simplemente vamos a incluir dentro de él, el contenido del fichero Eicar y mostrar un mensaje por pantalla.
La prueba a realizar será ver la posible detección de una posible "carga" al chequearlo por ejemplo desde VirusTotal.

Salimos al terminal y preparamos la zona de trabajo para Go:

# Crear directorio para codigo de GO:
mkdir ~/virus-go
cd ~/virus-go

# Preparar ruta actual para GO (generará un fichero go.mod):
go mod init virus
go mod tidy

Creamos un fichero virus.go y lo editamos, escribiendo el siguiente código dentro de él:

Fijate que en la cadena de texto virusillo, se está usando las comillas ` y no las '

Ahora simplemente ejecutamos lo siguiente en la terminal:

# Compilar para Linux (linux+64Bits)
go build -o virus.bin

# Compilar para Windows (Win+64Bits)
GOOS=windows GOARCH=amd64 go build -o virus.exe

# Compilar para MacOS (ARM)
GOOS=darwin GOARCH=arm64 go build  -o virus_macos.bin

Chequeando el "virus" en VirusTotal

Abrimos desde nuestro navegador la url de VirusTotal y vamos a comprobar que nos detecta.

VirusTotal
VirusTotal
Web de VirusTotal para subir y detectar virus en ficheros

Detección de eicar.txt
El fichero que contiene la cadena, es correctamente detectado.

Detección de eicar.txt

Detección de virus.bin (linux)
Ohhh! El binario se considera correcto en los sistemas de VirusTotal.

Detección de virus.exe (windows)
Sólo 9 de 72 herramientas de VirusTotal puede localizar la "carga"

Detección de virus_macos.bin (MacOS)
Ohhh! En el binario generado para MacOS, tampoco se detecta la carga genérica de Eicar File Test.

Ofuscando ejecutables mediante UPX

La herramienta UPX, realiza una compresión de binarios para casi cualquier arquitectura y tipo de sistemas operativo. Permite reducir el tamaño del fichero y en tiempo de ejecución descomprime en memoria y ejecuta el binario que contiene.
Este proceso legítimo puede ser usado para realizar una ofuscación mayor en ejecutables que puede complicar la detección temprana de malware y tipos de "payloads" que puedan ir embebidos en cualquier ejecutable.

El uso de upx es realmente sencillo, tan solo tenemos que indicar nombre del binario a incluir y el nombre del fichero a generar mediante el parámetro -o

El propio upx, determina el tipo de fichero resultante a generar, os muestro como se realizaría para generar binarios que se puedan ejecutar en otros sistemas operativos, al fichero resultante le pongo el prefijo upx- para indentificarlo de forma más sencilla:

Compresión de virus.bin (linux)
Compresión de virus.exe (windows)
Compresión de virus_macos.bin (MacOS)

Podeis de nuevo realizar las comprobaciones en VirusTotal e ir probando los distintos valores que ofrece upx para ver si se puede eludir la detección en aquellos sistemas en los que previamente si se detectaba.

Falsos Positivos con UPX

Habrás visto que al usar UPX, hay más detecciones como "virus" que antes, esto es debido a que actualmente se sabe que muchos "payloads" se cargan con este tipo de programas y por defecto los antivirus avisan de que este tipo de ficheros se consideran peligrosos.

Nota final sobre el artículo

Debido a que el resultado de upx es un binario empaquetado, en el proceso de ejecución y de extracción del mismo por UPX, en la segunda o tercera etapa del proceso de extracción, el "malware", en su mayoría será una inyección de memoria y un "binario mapeado", por lo que la herramienta UPX no funcionará como un cargador de "payload".

El artículo es un primer acercamiento a lenguajes que permiten compilaciones cruzadas de modo sencillo hacia otros sistemas operativos y mostrar alguna herramientas de compresión de binarios.
También sirve como recordatorio de el porqué siempre debemos de ejecutar programas de fuentes conocidas y fiables, pues no todos los antivirus son efectivos en la detección de virus y malware.

Espero que os haya gustado.

Etiquetas

Luis GuLo

🐧 SysAdmin GNU/Linux - 🐳 Docker - 🖥️ Bash Scripting - 🐪 Perl - 🐬 MySQL - 👥 Formador de TI - 👥 Formador de SysAdmin's - 💢 Ansible - ☁️ Cloud Computing - ❤️ Debian GNU/Linux