3. Control de secuencias de comandos
Entrada y Salida¶
Control de entrada¶
Este paso es muy importante ya que permite hacer que el script espere nuestras instrucciones, eso lo podemos lograr con read, veamos un ejemplo
# Available options
<SNIP>
echo -e "Additional options available:"
echo -e "\t1) Identify the corresponding network range of target domain."
echo -e "\t2) Ping discovered hosts."
echo -e "\t3) All checks."
echo -e "\t*) Exit.\n"
read -p "Select your option: " opt
case $opt in
"1") network_range ;;
"2") ping_host ;;
"3") network_range && ping_host ;;
"*") exit 0 ;;
esac
el parámetro -p que acompaña a read sirve para indicarle al script que la entrada permanezca en la misma Linea
Control de salida¶
Ya hemos aprendido sobre las redirecciones de salida de la salida en el módulo Fundamentos de Linux. Sin embargo, el problema con las redirecciones es que no obtenemos ninguna salida del comando respectivo. Se redirigirá al archivo correspondiente. Si nuestros scripts se vuelven más complicados más adelante, pueden tardar mucho más tiempo que unos pocos segundos. Para evitar quedarnos inactivos y esperar los resultados de nuestro script, podemos usar la utilidad [[https://man7.org/linux/man-pages/man1/tee.1.html | tee]]. Esta garantiza que veamos los resultados que obtenemos inmediatamente y que se almacenen en los archivos correspondientes. En nuestro script CIDR.sh, hemos usado esta utilidad dos veces de diferentes maneras.
<SNIP>
# Identify Network range for the specified IP address(es)
function network_range {
for ip in $ipaddr
do
netrange=$(whois $ip | grep "NetRange\|CIDR" | tee -a CIDR.txt)
cidr=$(whois $ip | grep "CIDR" | awk '{print $2}')
cidr_ips=$(prips $cidr)
echo -e "\nNetRange for $ip:"
echo -e "$netrange"
done
}
<SNIP>
# Identify IP address of the specified domain
hosts=$(host $domain | grep "has address" | cut -d" " -f4 | tee discovered_hosts.txt)
<SNIP>
Al utilizar tee, transferimos la salida recibida y utilizamos la barra vertical (|) para reenviarla a tee. El parámetro "-a / --append" garantiza que el archivo especificado no se sobrescriba, sino que se complete con los nuevos resultados. Al mismo tiempo, nos muestra los resultados y cómo se encontrarán en el archivo.
1i8n@htb[/htb]$ cat discovered_hosts.txt CIDR.txt
165.22.119.202
NetRange: 165.22.0.0 - 165.22.255.255
CIDR: 165.22.0.0/16
Control de flujo - Bucles¶
El control del flujo de nuestros scripts es esencial. Ya hemos aprendido sobre las condiciones if-else, que también forman parte del control de flujo. Después de todo, queremos que nuestro script funcione de manera rápida y eficiente, y para ello, podemos utilizar otros componentes para aumentar la eficiencia y permitir un procesamiento sin errores. Cada estructura de control es una rama o un bucle. Las expresiones lógicas de valores booleanos generalmente controlan la ejecución de una estructura de control. Estas estructuras de control incluyen:
- Branches:
- If-Else Conditions
- Case Statements
- Loops:
- For Loops
- While Loops
- Until Loops
Bucles For¶
Iterando listas¶
for variable in 1 2 3 4
do
echo $variable
done
iterando archivos¶
for variable in file1 file2 file3
do
echo $variable
done
Iterando IPv4¶
for ip in "10.10.10.170 10.10.10.174 10.10.10.175"
do
ping -c 1 $ip
done
Tambien podemos escribirlo com un comando de una sola Linea, es decir directamente el la terminal
1i8n@htb[/htb]$ for ip in 10.10.10.170 10.10.10.174;do ping -c 1 $ip;done
PING 10.10.10.170 (10.10.10.170): 56 data bytes
64 bytes from 10.10.10.170: icmp_seq=0 ttl=63 time=42.106 ms
--- 10.10.10.170 ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 42.106/42.106/42.106/0.000 ms
PING 10.10.10.174 (10.10.10.174): 56 data bytes
64 bytes from 10.10.10.174: icmp_seq=0 ttl=63 time=45.700 ms
--- 10.10.10.174 ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 45.700/45.700/45.700/0.000 ms
Ejemplo¶
<SNIP>
# Identify Network range for the specified IP address(es)
function network_range {
for ip in $ipaddr
do
netrange=$(whois $ip | grep "NetRange\|CIDR" | tee -a CIDR.txt)
cidr=$(whois $ip | grep "CIDR" | awk '{print $2}')
cidr_ips=$(prips $cidr)
echo -e "\nNetRange for $ip:"
echo -e "$netrange"
done
}
<SNIP>
Bucles While¶
El bucle while es conceptualmente simple y sigue el siguiente principio: - Una declaración se ejecuta siempre que se cumpla una condición (sea verdadera).
<SNIP>
stat=1
while [ $stat -eq 1 ]
do
ping -c 2 $host > /dev/null 2>&1
if [ $? -eq 0 ]
then
echo "$host is up."
((stat--))
((hosts_up++))
((hosts_total++))
else
echo "$host is down."
((stat--))
((hosts_total++))
fi
done
<SNIP>
Trabajando con contadores¶
#!/bin/bash
counter=0
while [ $counter -lt 10 ]
do
# Increase $counter by 1
((counter++))
echo "Counter: $counter"
if [ $counter == 2 ]
then
continue
elif [ $counter == 4 ]
then
break
fi
done
Until Loops¶
También existe el bucle Until, que es relativamente poco común. Sin embargo, el bucle Until funciona exactamente como el bucle While, pero con la diferencia:
- El código dentro de un bucle hasta se ejecuta siempre que la condición particular sea falsa.
#!/bin/bash
counter=0
until [ $counter -eq 10 ]
do
# Increase $counter by 1
((counter++))
echo "Counter: $counter"
done
1i8n@htb[/htb]$ ./Until.sh
Counter: 1
Counter: 2
Counter: 3
Counter: 4
Counter: 5
Counter: 6
Counter: 7
Counter: 8
Counter: 9
Counter: 10
Ejercicio de practica¶
#!/bin/bash
# Decrypt function
function decrypt {
MzSaas7k=$(echo $hash | sed 's/988sn1/83unasa/g')
Mzns7293sk=$(echo $MzSaas7k | sed 's/4d298d/9999/g')
MzSaas7k=$(echo $Mzns7293sk | sed 's/3i8dqos82/873h4d/g')
Mzns7293sk=$(echo $MzSaas7k | sed 's/4n9Ls/20X/g')
MzSaas7k=$(echo $Mzns7293sk | sed 's/912oijs01/i7gg/g')
Mzns7293sk=$(echo $MzSaas7k | sed 's/k32jx0aa/n391s/g')
MzSaas7k=$(echo $Mzns7293sk | sed 's/nI72n/YzF1/g')
Mzns7293sk=$(echo $MzSaas7k | sed 's/82ns71n/2d49/g')
MzSaas7k=$(echo $Mzns7293sk | sed 's/JGcms1a/zIm12/g')
Mzns7293sk=$(echo $MzSaas7k | sed 's/MS9/4SIs/g')
MzSaas7k=$(echo $Mzns7293sk | sed 's/Ymxj00Ims/Uso18/g')
Mzns7293sk=$(echo $MzSaas7k | sed 's/sSi8Lm/Mit/g')
MzSaas7k=$(echo $Mzns7293sk | sed 's/9su2n/43n92ka/g')
Mzns7293sk=$(echo $MzSaas7k | sed 's/ggf3iunds/dn3i8/g')
MzSaas7k=$(echo $Mzns7293sk | sed 's/uBz/TT0K/g')
flag=$(echo $MzSaas7k | base64 -d | openssl enc -aes-128-cbc -a -d -salt -pass pass:$salt)
}
# Variables
var="9M"
salt=""
hash="VTJGc2RHVmtYMTl2ZnYyNTdUeERVRnBtQWVGNmFWWVUySG1wTXNmRi9rQT0K"
# Base64 Encoding Example:
# $ echo "Some Text" | base64
# <- For-Loop here
# Check if $salt is empty
if [[ ! -z "$salt" ]]
then
decrypt
echo $flag
else
exit 1
fi
# Crea un bucle "For" que codifique la variable "var" 28 veces en "base64". La cantidad de caracteres del hash número 28 es el valor que se debe asignar a la variable "salt".
Solución¶
#!/bin/bash
# Decrypt function
function decrypt {
MzSaas7k=$(echo $hash | sed 's/988sn1/83unasa/g')
Mzns7293sk=$(echo $MzSaas7k | sed 's/4d298d/9999/g')
MzSaas7k=$(echo $Mzns7293sk | sed 's/3i8dqos82/873h4d/g')
Mzns7293sk=$(echo $MzSaas7k | sed 's/4n9Ls/20X/g')
MzSaas7k=$(echo $Mzns7293sk | sed 's/912oijs01/i7gg/g')
Mzns7293sk=$(echo $MzSaas7k | sed 's/k32jx0aa/n391s/g')
MzSaas7k=$(echo $Mzns7293sk | sed 's/nI72n/YzF1/g')
Mzns7293sk=$(echo $MzSaas7k | sed 's/82ns71n/2d49/g')
MzSaas7k=$(echo $Mzns7293sk | sed 's/JGcms1a/zIm12/g')
Mzns7293sk=$(echo $MzSaas7k | sed 's/MS9/4SIs/g')
MzSaas7k=$(echo $Mzns7293sk | sed 's/Ymxj00Ims/Uso18/g')
Mzns7293sk=$(echo $MzSaas7k | sed 's/sSi8Lm/Mit/g')
MzSaas7k=$(echo $Mzns7293sk | sed 's/9su2n/43n92ka/g')
Mzns7293sk=$(echo $MzSaas7k | sed 's/ggf3iunds/dn3i8/g')
MzSaas7k=$(echo $Mzns7293sk | sed 's/uBz/TT0K/g')
flag=$(echo -n "$MzSaas7k" | base64 -d | openssl enc -aes-128-cbc -d -a -A -k $salt)
}
# Variables
var="9M"
salt=""
hash="VTJGc2RHVmtYMTl2ZnYyNTdUeERVRnBtQWVGNmFWWVUySG1wTXNmRi9rQT0K"
# Base64 encoding 28 times
for i in {1..28}
do
var=$(echo "$var" | base64)
done
# Assign the length of the 28th encoded string to salt
# add +1 to the length of the string to account for the null terminator
salt=$((${#var} + 1))
# Check if $salt is empty
if [[ ! -z "$salt" ]]
then
decrypt
echo "$flag"
else
exit 1
fi
output¶
*** WARNING : deprecated key derivation used.
Using -iter or -pbkdf2 would be better.
HTBL00p5r0x