SHAR / Incrustar TAR en ficheros bash

Linux Nivel Medio 14 de dic. de 2022

El método sirve como solución para incluir en un unico script varios ficheros (embebidos en un fichero .tar, por ejemplo) o como solución para una 'ofuscación sencilla de scripts'.

En algún momento puede que nos surga la necesidad de disponer de algún script que no queramos que sea leido por algunas personas y además controlar que no es modificado por nadie.

Hoy os traigo una solución 'sencilla' de ofuscación para ello, vamos a detallar con pasos con un ejemplo que es la forma más sencilla de verlo.

La solución pasa por varios pasos:

    Construcción del script
    Empaquetar/Comprimir el script
    Incrustar el script dentro del script 'lanzador'

CREACIÓN DEL SCRIPT

Vamos a crear un script muy simple que nos indique el nombre de nuestro usuario y nuestro id.

Para ello creamos el fichero y ajustamos los permisos de ejecución:

touch script.sh
chmod +x script.sh

Lo editamos con nuestro editor favorito (vi, nano, etc...) y ponemos el siguiente código:

#!/bin/bash
# Obtener nombre
USUARIO=$(whoami)
# Obtener id
IDUSUARIO=$(id -u -r)
echo
echo
"---------------------------------------------------------------"
echo " Su Usuario es: $USUARIO y con ID: $IDUSUARIO"
echo "---------------------------------------------------------------"
echo

Lo guardamos y comprobamos que funciona:

./script.sh

---------------------------------------------------------------
  Su Usuario es: luisgulo y con ID: 1000
---------------------------------------------------------------

COMPRIMIR EL SCRIPT

Una vez hemos comprobado que el script funciona, vamos a comprimirlo.

Nota: Podemos comprimirlo con la utilidad que deseeemos (Zip, Rar, Gzip, cpio, etc.)

Para nuestro ejemplo lo almacenaremos con formato gzip dentro de un tar:

tar czvfp script.sh.tar.gz script.sh

Dispondremos de 2 ficheros:

$ ls -1 script*
script.sh
script.sh.tar.gz

SCRIPT LANZADOR

Ahora necesitamos un script en el que incrustar o embeber nuestro 'script' para que no se vea.

Podemos incluso incluir dentro de él la comprobación del MD5, el valor del MD5 lo podemos generar así:

md5sum script.sh|awk '{print $1}'
d7efbc743ba0d0f5b7ad723d3e52d22f

Ahora vamos a crear el script 'lanzador' (podemos ponerle el nombre que deseemos):

touch lanzador.sh
chmod 755 lanzador.sh

Lo editamos e incluimos el siguiente código:

#!/bin/bash
# LGL. Ejecucion bash ofuscada v2 (En memoria)
# Nota: Elimine los comentarios para mayor ofuscacion
# Valor MD5 (no modificar si no queremos usarlo)
MD5='VALORMD5'
# OF1: Localizar donde se escuentra el script 'ofuscado'
OF1=$(awk '/^_OFUSCADO_/ { print NR + 1; exit 0; }' $0)
# SCRIPT: Localizar el nombre de este mismo script (autobusqueda)
SCRIPT=$(pwd)"/"$0
# Comprobar MD5 si es neceario
if [ "$MD5" != "VALORMD5" ] ; then
  # Hay valor MD5, debemos comprobarlo
  CHEQUEO=$(tail -n +$OF1 $SCRIPT |tar -xOz |md5sum -|awk '{print $1}')
  # Realizar comprobacions para el/los ficheros
  if [ "$CHEQUEO" != "$MD5" ] ; then
     # Si no coinciden realizar salida con error (exit 1)
     echo "Error MD5 en validacion del script"
     echo "Abortando Ejecución"            
     exit 1
  fi
fi      
# Todo correcto. Lanzamos el scritp interno
tail -n +$OF1 $SCRIPT |tar -xOz |bash -
exit 0
_OFUSCADO_

Este script es la base sobre la que incrustaremos el anterior .tar.gz del script.sh que hemos creado antes.

Tiene algunas 'particularidades':

a) Si incluimos el valor del MD5 del script se comprobará y si no coincide se abortará la ejecucion
b) No hace falta indicar el nombre de nuestro script incrustrado. Pero tiene la limitación de sólo ejecutar un único script
c) Se descomprime 'al vuelo' (en memoria) para que no sea visible por todos el mundo a la hora de extraerlo y ejecutarlo

IMPORTANTE: Despues de la linea _OFUSCADO_ no puede haber ninguna línea nueva o no funcionará

INCRUSTACIÓN DEL SCRIPT

Vamos a unir el fichero lanzador.sh y el fichero script.tar.gz en un único fichero.

Una vez creado el fichero 'lanzador.sh', opcionalmente podemos incluir la suma MD5, si queremos se compruebe esto.

Vamos a crear el script final que se va a llamar ofuscado.sh

Para unirlos nos sirve perfectamente el comando cat:

cat lanzador.sh script.tar.gz >> ofuscado.sh
chmod 755 ofuscado.sh

Con eso tenemos creado el script final y con los permisos de ejecución necesarios.

Podemos comprobar su contenido para ver la 'ofuscación', mediante el comando cat o incluso intentar extraer algo de información del mismo mediante el comando strings, y vemos que no se ve claramente el contenido del script incrustado.

Ahora solo falta comprobar que el script ofuscado.sh funciona:

./ofuscado.sh

---------------------------------------------------------------
   Su Usuario es: luisgulo y con ID: 1000
---------------------------------------------------------------

VERSION 2. INCLUSIÓN DE MULTIPLES SCRIPTS

Me han planteado un reto como mejora, la posibilidad de incluir multiples scripts embebidos en el mismo fichero y la comprobación además de sus MD5 (o cualquier otro hash que deseemos)

La solución es bastante sencilla tambien:

1) Crear todos los scripts necesarios y un fichero 'control.md5' que contenga el hash de comprobación.

ls -1 script_*
  script_1
  script_2
  script_3
  script_4
  script_5

Creamos el md5sum:

md5sum script_* > control.md5

2) Comprimir los scripts e incluir además 'control.md5':

tar czvfp multiples_scripts.tar.gz script_* control.md5

3) Modificamos el script para que permitar lanzar cualquiera de los scripts embebidos. Lo llamaremos lanzador_v2.sh

touch lanzador_v2.sh
chmod 755 lanzador_v2.sh

Lo editamos para obtener el siguiente código:

#!/bin/bash
# LGL. Ejecucion bash ofuscada v2 (En memoria y de multiples scripts embevidos)
# Nota: Elimine los comentarios para mayor ofuscacion
# Valor MD5 (no modificar si no queremos usarlo)

# Recibimos como parametro el nombre de cualquiera de los scripts internos a ejecutar
EJECUTA=$1
if [ "$EJECUTA" = "" ] ; then
   echo "ERROR:"
   echo "No se ha indicado el script a ejecutar"
   exit 1   
fi    
MD5='N' # Valores posibles: S/N
# OF1: Localizar donde se escuentra el script 'ofuscado'
OF1=$(awk '/^_OFUSCADO_/ { print NR + 1; exit 0; }' $0)
# SCRIPT: Localizar el nombre de este mismo script (autobusqueda)
SCRIPT=$(pwd)"/"$0

# Si no existe el script en el fichero embebido dentro salimos
RETORNO=$(tail -n +$OF1 $SCRIPT |tar tzf -|grep $EJECUTA|wc -l)
if [ "$RETORNO" != "1" ] ; then
   echo "ERROR:"
   echo "El script indicado no existe"
   exit 1
fi
# Comprobar MD5 si es necesario (valor almacenado en fichero control.md5)
if [ "$MD5" = "S" ] ; then
  # Si el Flag MD5 tiene SI debemos comprobar el MD5 del fichero a ejecutar
  CHEQUEO=$(tail -n +$OF1 $SCRIPT |tar -xOz $EJECUTA |md5sum -|awk '{print $1}')
  CONTROL=$(tail -n +$OF1 $SCRIPT |tar -xOz control.md5 |grep $EJECUTA|awk '{print $1}')
  # Realizar comprobacions para el/los ficheros
  if [ "$CHEQUEO" != "$CONTROL" ] ; then
     # Si no coinciden realizar salida con error (exit 1)
     echo "Error MD5 en validacion del script"
     echo "Abortando Ejecución"            
     exit 1
  fi
fi      
# Todo correcto. Lanzamos el script interno recibido como parametro
tail -n +$OF1 $SCRIPT |tar -xOz $EJECUTA |bash -
exit 0
_OFUSCADO_

Incrustamos en el script lanzador_v2.sh con el contenido del .tar.gz que contiene todos los scripts:

cat lanzador_v2.sh multiples_scripts.tar.gz >> ofuscado2.sh
chmod 755 ofuscado2.sh

Ya tenemos nuestro fichero ofuscado2.s. Para su uso tan solo hay que pasarle como parámetro el nombre del script 'embebido' que deseamos ejecutar, por ejemplo para lanzar el script_2 escribiremos:

./ofuscado2.sh script_2

Además, si a la variable MD5 (que tiene como valor por defecto "N") le cambiamos el valor a "S", se realizará la comprobación de su valor MD5 (o función hash deseada) para comprobar que no ha sido modificado.

Etiquetas

Luis GuLo

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