SHAR / Incrustar TAR en ficheros bash
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.shchmod +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.shDispondremos 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.shchmod 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.