Convierta el script bash en un ejecutable binario independiente compilado, no en texto
Quiero hacer un script Bash ejecutable por el kernel. Ya he usado el chmod +xcomando y #!/bin/bashhacerlo ejecutable y funciona, pero lo que quiero hacer es convertirlo en un ejecutable sin intérprete, como un ejecutable de una aplicación compilada.
¿Hay alguna forma de que pueda hacer esto? Todo lo que necesito es una forma de hacer que el script Bash sea ejecutable desde el kernel de macOS y no necesito especificar un shebang. Tampoco quiero que nadie pueda abrirlo con edición de texto o similar y pueda ver el código.
Respuestas
Como ya ha publicado jksoegaard , existe el comando shc. A continuación se muestra un ejemplo de cómo instalar y utilizar este comando. Probé esta respuesta usando macOS Big Sur.
Estos son los pasos que utilicé para instalar shc.
Abra la Terminal presionando command+ space, luego escriba
terminaly presione la Entertecla.Primero instale homebrew .
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" < /dev/null 2> /dev/nullInstale shc .
brew install shc
A continuación se muestra una lista del archivo de secuencia de comandos de prueba denominado hello.sh.
#!/bin/bash
osascript -e 'display dialog "Hi There"' >/dev/null'
Estos son los pasos que utilicé para crear y probar el ejecutable.
Ingrese el siguiente comando para compilar el script usando
shc.shc -f hello.shIngrese el siguiente comando para cambiar el nombre del ejecutable.
mv hello.sh.x helloIngrese el comando para probar.
./helloA continuación se muestra el cuadro de diálogo resultante.
Apéndice
A continuación se muestra el resultado de ejecutar los comandos.
Last login: Thu Oct 8 06:36:48 on console
dma@dmas-Mac-mini ~ % ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" < /dev/null 2> /dev/null
Password:
==> You are using macOS 11.0.
==> We do not provide support for this pre-release version.
This installation may not succeed.
After installation, you will encounter build failures with some formulae.
Please create pull requests instead of asking for help on Homebrew\'s GitHub,
Discourse, Twitter or IRC. You are responsible for resolving any issues you
experience while you are running this pre-release version.
==> This script will install:
/usr/local/bin/brew
/usr/local/share/doc/homebrew
/usr/local/share/man/man1/brew.1
/usr/local/share/zsh/site-functions/_brew
/usr/local/etc/bash_completion.d/brew
/usr/local/Homebrew
==> The following existing directories will be made group writable:
/usr/local/bin
==> The following existing directories will have their owner set to dma:
/usr/local/bin
==> The following existing directories will have their group set to admin:
/usr/local/bin
==> The following new directories will be created:
/usr/local/etc
/usr/local/include
/usr/local/lib
/usr/local/sbin
/usr/local/share
/usr/local/var
/usr/local/opt
/usr/local/share/zsh
/usr/local/share/zsh/site-functions
/usr/local/var/homebrew
/usr/local/var/homebrew/linked
/usr/local/Cellar
/usr/local/Caskroom
/usr/local/Homebrew
/usr/local/Frameworks
==> The Xcode Command Line Tools will be installed.
==> /usr/bin/sudo /bin/chmod u+rwx /usr/local/bin
==> /usr/bin/sudo /bin/chmod g+rwx /usr/local/bin
==> /usr/bin/sudo /usr/sbin/chown dma /usr/local/bin
==> /usr/bin/sudo /usr/bin/chgrp admin /usr/local/bin
==> /usr/bin/sudo /bin/mkdir -p /usr/local/etc /usr/local/include /usr/local/lib /usr/local/sbin /usr/local/share /usr/local/var /usr/local/opt /usr/local/share/zsh /usr/local/share/zsh/site-functions /usr/local/var/homebrew /usr/local/var/homebrew/linked /usr/local/Cellar /usr/local/Caskroom /usr/local/Homebrew /usr/local/Frameworks
==> /usr/bin/sudo /bin/chmod g+rwx /usr/local/etc /usr/local/include /usr/local/lib /usr/local/sbin /usr/local/share /usr/local/var /usr/local/opt /usr/local/share/zsh /usr/local/share/zsh/site-functions /usr/local/var/homebrew /usr/local/var/homebrew/linked /usr/local/Cellar /usr/local/Caskroom /usr/local/Homebrew /usr/local/Frameworks
==> /usr/bin/sudo /usr/sbin/chown dma /usr/local/etc /usr/local/include /usr/local/lib /usr/local/sbin /usr/local/share /usr/local/var /usr/local/opt /usr/local/share/zsh /usr/local/share/zsh/site-functions /usr/local/var/homebrew /usr/local/var/homebrew/linked /usr/local/Cellar /usr/local/Caskroom /usr/local/Homebrew /usr/local/Frameworks
==> /usr/bin/sudo /usr/bin/chgrp admin /usr/local/etc /usr/local/include /usr/local/lib /usr/local/sbin /usr/local/share /usr/local/var /usr/local/opt /usr/local/share/zsh /usr/local/share/zsh/site-functions /usr/local/var/homebrew /usr/local/var/homebrew/linked /usr/local/Cellar /usr/local/Caskroom /usr/local/Homebrew /usr/local/Frameworks
==> /usr/bin/sudo /bin/mkdir -p /Users/dma/Library/Caches/Homebrew
==> /usr/bin/sudo /bin/chmod g+rwx /Users/dma/Library/Caches/Homebrew
==> /usr/bin/sudo /usr/sbin/chown dma /Users/dma/Library/Caches/Homebrew
==> Searching online for the Command Line Tools
==> /usr/bin/sudo /usr/bin/touch /tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress
==> Installing Command Line Tools for Xcode-12.0
==> /usr/bin/sudo /usr/sbin/softwareupdate -i Command\ Line\ Tools\ for\ Xcode-12.0
Software Update Tool
Finding available software
Downloading Command Line Tools for Xcode
Downloaded Command Line Tools for Xcode
Installing Command Line Tools for Xcode
Done with Command Line Tools for Xcode
Done.
==> /usr/bin/sudo /bin/rm -f /tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress
Password:
==> /usr/bin/sudo /usr/bin/xcode-select --switch /Library/Developer/CommandLineTools
==> Downloading and installing Homebrew...
HEAD is now at f84b9a027 Merge pull request #8878 from reitermarkus/upgrade-casks
==> Homebrew is run entirely by unpaid volunteers. Please consider donating:
https://github.com/Homebrew/brew#donations
Already up-to-date.
==> Installation successful!
==> Homebrew has enabled anonymous aggregate formulae and cask analytics.
Read the analytics documentation (and how to opt-out) here:
https://docs.brew.sh/Analytics
No analytics data has been sent yet (or will be during this `install` run).
==> Homebrew is run entirely by unpaid volunteers. Please consider donating:
https://github.com/Homebrew/brew#donations
==> Next steps:
- Run `brew help` to get started
- Further documentation:
https://docs.brew.sh
dma@dmas-Mac-mini ~ % brew install shc
Updating Homebrew...
==> Auto-updated Homebrew!
Updated 1 tap (homebrew/core).
==> Updated Formulae
Updated 4 formulae.
Warning: You are using macOS 11.0.
We do not provide support for this pre-release version.
You will encounter build failures with some formulae.
Please create pull requests instead of asking for help on Homebrew's GitHub,
Discourse, Twitter or IRC. You are responsible for resolving any issues you
experience while you are running this pre-release version.
==> Downloading https://homebrew.bintray.com/bottles/shc-4.0.3.catalina.bottle.tar.gz
######################################################################## 100.0%
==> Pouring shc-4.0.3.catalina.bottle.tar.gz
🍺 /usr/local/Cellar/shc/4.0.3: 17 files, 101.2KB
dma@dmas-Mac-mini ~ % pwd
/Users/dma
dma@dmas-Mac-mini ~ % cd Documents
dma@dmas-Mac-mini Documents % shc -f hello.sh
dma@dmas-Mac-mini Documents % mv hello.sh.x hello
dma@dmas-Mac-mini Documents % ./hello
Echaría un vistazo a un proyecto llamado shc (compilador de scripts de Shell).
https://github.com/neurobin/shc
Toma un script de shell y lo compila en código fuente C. El código fuente de C se puede compilar con un compilador de C estándar en un ejecutable binario.
Esto le permite ejecutar el script que ha creado sin que el contenido del script de shell se revele inmediatamente en texto claro. Sería un ejecutable binario como tantos otros.
Puede que sea necesario un poco de prueba y error para que shc analice su script específico dependiendo de las funciones avanzadas que esté usando en su script bash, pero esto debería llevarlo la mayor parte del camino.
Tenga en cuenta que el programa realmente solo cifra su script de shell y lo integra dentro del binario. Cuando se ejecuta el binario, la secuencia de comandos se descifra y se ejecuta nuevamente usando el shell ordinario. Para los programadores sería trivial romper esto para revelar el contenido de su script, pero para ocultar el contenido del script al usuario doméstico promedio, tal vez sea suficiente.
Si tiene HomeBrew instalado, puede instalarlo shcejecutando el siguiente comando en la Terminal:
brew install shc
Entonces es solo cuestión de ejecutar shcpara convertir su script en un binario:
shc -U -f myscript.sh -o mybinary
El comando mybinary es entonces el producto terminado.
Bash es técnicamente un lenguaje interpretado , no está compilado; compilarlo no es posible.
Bash es el intérprete del lenguaje de comandos o shell para el sistema operativo GNU.
Sin embargo, es posible ofuscarlo para que las miradas indiscretas no puedan mirar su guión.
Utilice openssl para codificar el archivo.
Creé un archivo de script Zsh simple llamado arraytest.shque se ejecutará en Zsh (es lo que tenía disponible en este momento). No voy a publicar el script de shell real, sino que voy a publicar la codificación base64.
En mi computadora, ejecuto el siguiente comando en mi script y obtengo los siguientes resultados:
% openssl base64 < arraytest.sh
IyEvYmluL3pzaAoKZGVjbGFyZSAtQSBwcm9ncz0oW2dzXT0iR2hvc3RzY3JpcHQi
IFtic109IkJ1bGxzaGl0IiBbYWJdPSJWb2RrYSIpCgoKbGV0IGFzaXplPSR7I3By
b2dzW0BdfQpsZXQgYnNpemU9JGFzaXplLTEKbGV0IGk9MQpmb3IgeCBpbiAiJHtw
cm9nc1tAXX0iOwpkbwogIGlmIFsgJGkgLWVxICRic2l6ZSBdICAgCiAgdGhlbgog
ICBwcmludGYgIiR4IGFuZCAiCiAgZWxpZiBbICRpIC1sZSAkYnNpemUgXSAmJiBb
ICRpIC1nZSAxIF0KICB0aGVuCiAgICBwcmludGYgIiR4LCAiCiAgZWxzZQogICAg
cHJpbnRmICIkeCIKICBmaQogICgoaSsrKSkKZG9uZQoKcHJpbnRmICIuXG4iCmVj
aG8gRG9uZS4KCg==
Esa salida debe guardarse en un archivo. Llamémoslo myencodedscript. Puede copiarlo y pegarlo en un archivo nuevo. No es necesario que lo haga ejecutable. Una vez que haya copiado ese script en su portapapeles, emita el comando
% pbpaste > myencodedscript
Ahora, debería tener un archivo llamado myencodedscript. A continuación, para ejecutarlo, debe retroalimentar esa codificación opensslpara decodificarla y luego canalizarla a su shell.
% cat myencodedscript | openssl base64 -d | zsh
Debería ejecutar el script y generar una salida a partir de una matriz asociativa.
Entonces, ¿cómo puedes hacer que esto sea autónomo?
#!/bin/zsh
#
#Script Name: encoded_script.sh
code="IyEvYmluL3pzaAoKZGVjbGFyZSAtQSBwcm9ncz0oW2dzXT0iR2hvc3RzY3JpcHQi
IFtic109IkJ1bGxzaGl0IiBbYWJdPSJWb2RrYSIpCgoKbGV0IGFzaXplPSR7I3By
b2dzW0BdfQpsZXQgYnNpemU9JGFzaXplLTEKbGV0IGk9MQpmb3IgeCBpbiAiJHtw
cm9nc1tAXX0iOwpkbwogIGlmIFsgJGkgLWVxICRic2l6ZSBdICAgCiAgdGhlbgog
ICBwcmludGYgIiR4IGFuZCAiCiAgZWxpZiBbICRpIC1sZSAkYnNpemUgXSAmJiBb
ICRpIC1nZSAxIF0KICB0aGVuCiAgICBwcmludGYgIiR4LCAiCiAgZWxzZQogICAg
cHJpbnRmICIkeCIKICBmaQogICgoaSsrKSkKZG9uZQoKcHJpbnRmICIuXG4iCmVj
aG8gRG9uZS4KCg=="
echo "$code" | openssl base64 -d | zsh
Guarde ese script como encoded_script.sh, hágalo ejecutable y luego ejecútelo con el comando./encoded_script.sh
Prima...
(Esto supone un escenario como un administrador que necesita ejecutar un script de forma discreta en 1 o más máquinas a su cargo).
Si realmente desea ocultar esto de las "miradas indiscretas", use este comando de una sola línea:
% openssl base64 < script.sh | ssh [email protected] ' openssl base64 -d | bash'
Esto codificará el script, lo canalizará a través de una conexión SSH donde decodifica el script y lo pasa al intérprete de shell.
chmod +x) Obviamente, necesita una cuenta en el control remoto y, aunque es bueno, pero no es obligatorio, las claves SSH habilitadas para que no tenga que ingresar una contraseña, especialmente si está ejecutando esto en un lote de máquinas.
Nota: Esto se hizo en Zsh con una matriz asociativa. Puede funcionar en Bash, pero necesitará al menos Bash versión 4 para funcionar correctamente. Además, no hay nada nefasto en el guión. Imprimirá 3 palabras y luego, en una nueva línea, la palabra "Listo" para indicar que el guión está terminado.
Si desea verificar que el código es realmente de mí, crear un archivo llamado myencodedscripten vi, pegar el código (sin comillas), asegúrese de pulsar "I" para "Insertar" antes de pegar, guardar y ejecutar el comando y comprobar el hash a continuación
% shasum -a 256 myencodedscript
d4fc6ce35480b0ace6ed0e1c910f1f40079a106b1914d767fa17ada02a422f88 myencodedscript
Solo funcionará si usa el mismo nombre de archivo. Probé esta plataforma cruzada en macOS y en FreeBSD. Si no obtiene el mismo hash, avíseme.
Como no está del todo claro qué es lo que realmente busca, lo que voy a sugerir es lo siguiente:
- Crea a partir de un
bashscript una estructura de paquete de aplicaciones con un solo ejecutable binario que no contiene en forma legible por humanos ninguno de los códigos de script utilizados para crearlo. - Se ejecuta como un paquete de aplicaciones macOS normal que se ejecuta como el nombre del paquete de aplicaciones .
- No abre Terminal durante su ejecución.
Dicho esto, todavía se puede interpretar porque si observa los archivos abiertos y puertos en el Monitor de actividad, el paquete de aplicaciones , por ejemplo, name.app , /bin/bashaparece en la lista.
Hay un proyecto de GitHub llamado bashapp que dice:
bashapp toma como entrada un script bash y genera un ejecutable binario y una estructura de directorio de aplicaciones OS X. Esto permite a los desarrolladores proporcionar scripts bash en los que se puede hacer clic en Finder sin que aparezcan terminales, etc. Útil para el lanzamiento, scripts de servicio, etc.
También proporciona un cifrado de fuente simple como un medio para ofuscar el script bash. Puede especificar su propia clave, o dejar que bashapp genere una clave aleatoria de tamaño aleatorio para usted, no menos de 32 bytes de longitud.
Necesitará tener las herramientas de línea de comandos para Xcode instaladas para compilar el bashapp ejecutable que crea el paquete de la aplicación . Consulte: Cómo instalar herramientas de línea de comandos en Mac OS X (sin Xcode) o en ejecución de Terminal :xcode-select --install
Dicho esto, hubo una cosa molesta en que el Dock Tile de la aplicación rebota en el Dock mientras se ejecuta. Una solución para esto es que no se muestre en el Dock ejecutando lo siguiente en la Terminal :
defaults write '/path/to/$name.app/Contents/Info.plist' LSUIElement -bool yes
Cambiando /path/to/$name.appsegún corresponda.
Un enfoque interesante para resolver este problema podría ser el uso de punteros de comprobación de procesos o la hibernación de procesos.
Básicamente, esto implicaría agregar un retraso de suspensión inicial al inicio de su script bash. Inicie el intérprete de bash como de costumbre, el script duerme y luego "hiberna" el proceso. Básicamente, esto guardaría su estado en un archivo binario en el disco.
Más tarde, puede reanudar el archivo (en cualquier computadora) que continuaría la ejecución de su programa.
Este es un método que no requiere volver a implementar el lenguaje de shell bash. Por otro lado, existe el riesgo de que esto se rompa con scripts grandes o similares, donde los descriptores de archivo tendrían que reabrirse automáticamente para que bash vuelva a leer el script (anulando el propósito de esta pregunta).
El único problema ahora es que no conozco una herramienta de hibernación de procesos para macOS en este momento. Por lo tanto, probablemente tendría que comenzar con la construcción de uno (o portar uno). Podría buscar soluciones para otros sistemas operativos, como por ejemplo las herramientas de Linux CRIU, CryoPID y ckpt.
Una forma muy aproximada de lograr algo similar a esto sería utilizar un sistema de virtualización como VMware o incluso algo como Docker en Mac. Ejecute el script dentro de Docker, por ejemplo, controle su contenedor cuando el script esté inactivo (el contenedor se detiene luego). Luego, elimine el script de shell del almacenamiento y, más tarde, podrá restaurar el contenedor para reanudar la ejecución.
No sé si esto hará lo que quieres, pero la aplicación gratuita Platypus tomará un script de línea de comandos y lo convertirá en una aplicación para Mac. También funciona con Python, Perl y otros scripts. Puede leer sobre esto en el enlace que proporcioné para ver si hará lo que desea. Nota: Usando mi método es posible ver el script original.