Latest Tweets

Transform your Hak5 Packet Squirrel into an automatic TOR annonymizer


I’ve been testing some Hak5 devices recently. I have to admit that they are all incredible, easy to use and well-designed. The Packet Squirrel is an incredible small MIPS device, based on OpenWRT, full of possibilities. Although its main goal is to perform advanced MitM attacks, it can be used for the common good as well. Being a MIPS device, some of the most used and well-known utilities and programs are included, but of course some others are not. TOR, for instance, it’s not installed out-of-the-box. That’s not a problem, of course, because you can always get its sources and cross-compile it. So I thought that using the Packet Squirrel for routing all the TCP traffic from a “TARGET” computer would be nice. Instead of using the device to perform MitM attacks, this would showcase its possibilities in quite another way.

Get to know the device

Before trying to cross-compile TOR, we need to know which libraries and hardware the device runs on. So we connect the device to our computer using the “ETH IN” device, we power it on and we connect to it using an SSH session. Then we perform the usual commands to get the standard C library used, its Kernel version, OpenSSL version, system architecture, and so on:

uname -a
Linux squirrel 3.18.45 #13 Mon Oct 30 21:24:27 UTC 2017 mips GNU/Linux

cat /proc/cpuinfo |grep model
cpu model : MIPS 24Kc V7.4

ls -l
lrwxrwxrwx 1 root root 21 Oct 30 21:24 ->

busybox |head -1
BusyBox v1.23.2 (2017-09-06 11:27:56 UTC) multi-call binary.

That’s fine; but we still need to know if the architecture is Big Endian or Little Endian, and of course if the processor is either MIPSR1, MIPSR2, or whatever. There are myriads of ways to do so, but we can just grab a binary from the squirrel and use readelf. The “busybox” binary will do:

readelf -h busybox |more
ELF Header:
Magic: 7f 45 4c 46 01 02 01 00 01 00 00 00 00 00 00 00
Class: ELF32
Data: 2’s complement, big endian
Version: 1 (current)
OS/ABI: UNIX – System V
ABI Version: 1
Type: EXEC (Executable file)
Machine: MIPS R3000
Version: 0x1
Entry point address: 0x4038a0
Start of program headers: 52 (bytes into file)
Start of section headers: 0 (bytes into file)
Flags: 0x74001005, noreorder, cpic, o32, mips16, mips32r2
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 7
Size of section headers: 0 (bytes)
Number of section headers: 0
Section header string table index: 0

Now we have everything we need to start the cross-compilation of TOR. The following table summarizes all of our findings:


Component Software Version
Standard C Library uClibc
SSL OpenSSL 1.0.0
Linux BusyBox 1.23.2
Kernel Kernel for MIPS 3.18.45
Architecture MIPS 32 Big Endian MIPS32R2

Setting up the cross-compilation framework

Although there are a bunch of ways to setup a cross-compilation framework, I have chosen Buildroot. After downloading this version, I have changed some basic things according to our previous table. Mind me, this version of Buildroot ships with newer versions of uClibc and OpenSSL, but we can fix that later on. You can find my configuration file for the buildroot framework here.

After performing the first compilation, I modified the uclibc and openssl packages to meet the Squirrel versions. According to the Buildroot documentation, there are some ways to customize your environment but I went the quick and dirty way instead. First, I did the following changes to build uClibc

  • I downloaded uClibc under $BUILDROOT/dl: wget
  • I added the sha256sum of uClibc- to $BUILDROOT/package/uclibc/uclibc.hash.
  • I changed uClibc version and package name in $BUILDROOT/package/uclibc/ accordingly.

After that, I did the same with the libopenssl package:

  • I downloaded libopenssl 1.0.0.s under $BUILDROOT/dl: wget
  • I added its sha256sum to $BUILDROOT/package/libopenssl/libopenssl.hash
  • I changed libopenssl version and package name in $BUILDROOT/package/libopenssl/
  • I commented out the LIBOPENSSL_PATCH variable in $BUILDROOT/package/libopenssl/
  • I moved all the patches to another directory to prevent the build system from applying them (because it was a different version, the patch command would fail): mv *.patch foo.

After all these changes, I performed the “make -j8” once again. At some point, when the libopenssl package was about to be installed, I got an error concerning the “install_docs” and “doc” rules. So I removed the “doc” directory from the EDIRS variable in $BUILDROOT/output/build/libopenssl-1.0.0s/Makefile along with the “install_docs” rule in the install rule. After performing the compilation again, the following error showed up: ../ file not recognized: File truncated. So I deleted this truncated file and executed “make -j8” again. This time the compilation ended without errors and the new libraries were sucessfully installed.

Finally, I removed the entire libevent from my previous built: rm -rf $BUILDROOT/output/build/libevent* and then I re-compiled it using the new OpenSSL libraries: make -j8. The buildroot environment was ready to use.

Cross-compiling TOR

Because our Packet Squirrel does not include the libevent library, I decided to build TOR statically linking libevent with the resulting binary. The PAcket Squirrel does not have support for some well-known modern protections, so I disabled any hardening during the compilation as well. The configure command I issued was this:

./configure –target=mips-buildroot-linux-uclibc –host=mips-buildroot-linux-uclibc –build=x86_64-pc-linux-gnu –prefix=/home/tonic as/buildroot/target/opt/tor –enable-static-libevent –with-libevent-dir=/home/buildroot/buildroot/build/libevent-2.1.8-stable/.libs/ –e nable-static-zlib –with-zlib-dir=/home/buildroot/buildroot/build/libzlib-1.2.11 –disable-gcc-hardening –disable-linker-hardening –disable-tool-name-check –disable-threads –disable-asciidoc

After that, I built and installed TOR: make -j8 install.

Finally, I copied all the files under $BUILDROOT/output/target/opt/tor to the Packet Squirrel, on its USB pendrive (previously formatted using EXT4): scp -r $BUILDROOT/output/target/opt/tor root@

The payload

Because this device does not have too much free space, I had to setup some directories on the USB pendrive to accommodate some TOR files (logfiles and the like). With that done, I wrote the following payload:

# TOR payload
# 2018 by T. Castillo Girona
# This is a simple payload that allows to route all the DNS queries and TCP
# traffic from a TARGET through TOR.
function grab_target_ip() {
	target_ip=`cat /tmp/dhcp.leases |awk '{print $3}'`
	if [ ! -z "$target_ip" ]; then
		# Set the led to BLUE:
		echo $target_ip
		# Set the LED to fail:
		echo "`date` STAGE2: TARGET IP : Not a DHCP lease" >> $LOGFILE
		echo ""
		# Stop the payload:
		exit 1
function start_tor() {
	if [ -x $TOR -a -r $TORCFG ]; then
		# Delete any previous log:
		rm -rf $TORLOG 2>/dev/null
		# Start tor:
		echo "`date` STAGE3: EXECUTING TOR" >> $LOGFILE
		$TOR -f $TORCFG	2>&1&
		# It may take a while until tor is ready; that's when
		# its log file says: Bootstrapped 100%: Done
		while [ true ]; do
			cat $TORLOG|grep "Bootstrapped 100%: Done" 2>/dev/null
			if [ $? -eq 0 ]; then
				# Perfect, we've got a circuit!:
				LED W
				echo "`date` STAGE3: WE HAVE A CIRCUIT " >> $LOGFILE
		# No tor binary or no torrc.
		# We leave it here.
		echo "`date` NO TOR OR NO TORRC FILE." >> $LOGFILE
function set_ip_tables() {
	# Enable redirection for UDP DNS packets:
	$IPTABLES -t nat -I PREROUTING 1 -p udp -i eth0 --dport 53 -j REDIRECT --to-ports 5353
	# Enable TCP redirection through TOR:
	# (don't enable redirection for
	$IPTABLES -t nat -I PREROUTING 2 -p tcp ! -d -i eth0 -j REDIRECT --to-ports 9040
function rerunTor() {
	echo "`date` STAGE4: RE-EXECUTING TOR " >> $LOGFILE
	# Get pid of TOR process and kill it:
	ptor=`pidof tor`
	if [ $? -eq 0 ]; then
		# Kill it:
		kill -9 $ptor
	# Re-execute it:
function run() {
	# Set networking to NAT
	# (we get an IP from the network; we assign an IP to the target)
	# The target gets routed through the Squirrel.
	sleep 20
	# Now, make sure our target has a valid IP assigned
	# by the squirrel. Case it has not, stop the payload.
	echo "`date` STAGE2: TARGET IP IS $targetip " >> $LOGFILE
	# Now, prepare our instance of Tor, make sure it is
	# running before doing anything else:
	echo "`date` STAGE3: STARTING TOR " >> $LOGFILE
	# Now set the iptables rules to redirect DNS and
	# TCP traffic trhough TOR transparently:
	# Let's set the LED to Success:
	# Every time the user press the button, we kill
	# tor, and re-run it again so that the circuit
	# gets changed every time.
	while [ true ]; do
		# Once the button has been pressed, proceed:
# This payload will only run if we have USB storage
[[ ! -f /mnt/NO_MOUNT ]] && {
	run &
} || {

This payload simply setup the Squirrel as a NAT device; it will get an IP from the network on its “ETH OUT” interface and it will assign a dynamic IP Address to the TARGET computer on its ETH IN device. All the traffic from the TARGET computer will be routed through the Squirrel, and thanks to the iptables rules, the UDP packets for DNS and all the TCP packets will be redirected through TOR. Everytime the button is pressed, TOR is killed and re-executed, so a new circuit is constructed.

This payload is far from being perfect, but it delivers. Feel free to improve this version. If you do not want to go through all the burden of cross-compiling TOR, you can download the binaries here. Just unzip it directly on the USB pendrive on the Packet Squirrel, copy the “” to the desired switch directory, and enjoy!

Una al Mes Mision 004: Write-Up


El cuarto reto de Una al Mes está dividido en 2 partes. Durante la primera parte debemos ser capaces de acceder a un servicio web sin conocer ninguna credencial. Una vez resuelta esta primera parte, podremos descargar un ejecutable Windows para X86_64 que nos devolverá la FLAG.

Primera parte: “esto va de galletas

Accedemos a la URL del reto ( y nos aparece el mensaje de error siguiente:

Mensaje de error durante el acceso a la URL del reto.

El mensaje de error podría indicar que el código del servidor comprueba el campo “User-Agent” enviado por el navegador del cliente. Sin embargo, esto es una falsa pista. Si miramos el código fuente de la página, observamos el siguiente código JavaScript:

      $.post('login.php', {"username": $('#fieldUser').val(), "password": $('#fieldPassword').val()}, function(val, status){
        if (val == "ok"){

Ya hemos identificado, pues, la página de login ( Tal y como se ve en el código anterior, la página recibe simplemente 2 parámetros, “username” y “password”. Aquí es donde podríamos pensar que se trata de un ejercicio de fuerza bruta, lanzando peticiones HTTP POST contra login.php hasta que logremos entrar como usuario “fry”. De nuevo, estamos equivocados. La función en JS obtenerCookie(), de la misma página, nos da una pista de que esto va de galletas:

 function obtenerCookie(clave) {
      var name = clave + "=";
      var ca = document.cookie.split(';');
      for(var i=0; i<ca.length; i++) {
          var c = ca[i];
          while (c.charAt(0)==' ') c = c.substring(1);
          if (c.indexOf(name) == 0) return c.substring(name.length,c.length);
      return "";

Ejecutamos Burp, hacemos una petición a inicio.php, y después enviamos dicha petición al módulo Repeater. Modificamos la URI por “login.php” y el método por “POST”. Finalmente añadimos el payload (username=test&password=test). Aunque no sabemos si la clave será idéntica al usuario, por probar que no sea:

Hacemos un POST contra login.php y el servidor nos deveuleve una cookie de sesión.

El servidor nos devuelve una cookie de sesión:


Esto cada vez parece más un clásico CTF donde, para poder seguir, debemos ser capaces de “cocinar” la cookie de sesión y suplantar al usuario “fry”. Usamos un gestor de cookies en nuestro Firefox y añadimos esta cookie de sesión. Después recargamos la página “inicio.php”. Esta vez, se nos saluda:

Acceso como usuario “test” en “inicio.php” con la cookie de sesión.

Por supuesto, para poder avanzar debemos entender como está generada la cookie. La función en JS “obtenerCookie()” mostrada unas líneas más arriba es la clave. Fijémonos que dicha función itera entre todas las posibles cookies y, por cada una elimina los espacios en blanco que puedan encontrarse al principio de la cookie (ejecuta un ltrim()). Finalmente, busca el valor pasado como parámetro (test en este caso) al principio de dicha cookie, y si lo encuentra retorna el valor después de dicha cadena. Por el valor codificado en base64 de la cookie, sabemos que la longitud en texto claro ASCII de la cookie debe ser de 10 bytes exactos.

Probamos de codificar en base64 la cadena ”      test”:

echo ” test”|tr -d ‘\n’|base64

Fijémonos que ICAgI podría ser substituido por qTImq, pero luego no tenemos dos patrones que se repitan en la cookie: CAgd != GVzd. Por el formato de la cookie obtenida, parecería que hay algún algoritmo de substitución que cifra el código base64 de la cookie.

Probamos ahora de codificar la cadena “test      “ en base64:

echo “test      “|tr -d ‘\n’|base64

Aquí tenemos una posible pista sobre el cifrado utilizado por la cookie. Fijémonos que dGVzd se traduce en qTImq en la cookie original; así vemos que d=>q; G=>T; V=>I; z=>m; d=>q …, y entre caracter y caracter tenemos una rotación de 13 caracteres. Además, tenemos los dos patrones claros CAgiCAgI. Así pues, probamos de cifrar nuestra cadena base64 usando ROT13:

Hemos descubierto la receta secreta.

Ahora que ya sabemos como “cocinar” nuestra cookie, cambiamos “test” por “fry”, añadiendo un espacio en blanco más (fry + 7 espacios en blanco). Codifcamos en base64 y ciframos usando ROT13:

echo “fry       “|tr -d ‘\n’|base64

El resultado es la cookie que mostramos a continuación:

Nuestra cookie acabada de salir del horno.

Sólo nos queda modificar la cookie en nuestro navegador por esta otra y recargar la página “inicio.php”. Esta vez obtenemos una URL con el archivo a descargar, segunda parte del reto:

Primera parte superada.

Segunda parte: “r2 es como el algodón, no engaña”

Descomprimimos el ZIP descargado; tenemos un ejecutable (test.exe) y un archivo que, probablemente, sea la FLAG cifrada: secretcode. Vemos que el ejecutable es un Windows de 64 bits para “consola”:

file test.exe
test.exe: PE32+ executable (console) x86-64, for MS Windows

Antes de ejecutar el binario, abrimos radare2 para analizarlo:

r2 -A test.exe

Nos situamos en la función main y observamos su código desensamblado:

Dentro de la función main de test.exe.

Aparte de comprobar si hay un depurador presente (jojojo, yo ni he picado porque he ido directo a leer el código desensamblado y no lo he llegado ni a depurar ;-)), vemos que hay una llamada a la función “check” antes de ejecutar el retorno y salir. Vamos a esa función y nos fijamos en su flujo de ejecución gracias al modo visual de r2:

El control path del programa que nos descifrará “secretcode”.

Parece evidente que el control path del programa debería acabar en la llamada a decrypt() para poder descifrar el archivo “secretcode“. Para llegar a dicha función, debemos pasar por la reproducción del sonido en la función “cool_melody()”. La flag la podemos ahora obtener de tres maneras diferentes:

  1. Ejecutamos el binario en modo emulación (ESIL) para que se ejecute la función decrypt sin tener ni que pasar por la ejecución del resto del programa.
  2. Analizamos la función decrypt() con r2 y, a partir de lo que parece la clave “tvB3Cj4iNxw4rjMNxhmX3DaXAuMG2e”, desciframos la FLAG.
  3. Seremos buenos, y analizaremos con r2 como llegar a la llamada de la función “cool_melody” y, desde allí, a “decrypt”.

 Para llegar a “cool_melody” basta con introducir en el parámetro pedido (número de pista) el valor 101 en decimal (0x65):

Si introducimos 101 como track, seguimos la ejecución y caemos en “cool_melody()”

La ejecución del programa seguirá hasta reproducir el “cool_melody” y nos hará una pregunta que es fácil de contestar porque la respuesta está hardcodeada en ASCII en el propio ejecutable “futurama“:

La respuesta a la pregunta está hardcodeada en el propio binario.

Así pues, sabemos que debemos escribir 101 como primer parámetro, y “futurama” como segundo en el programa. Esto hará que el control path del programa acabe en el OFFSET 0x401b99, abra el archivo “secretode”, y lo descifre con una llamada a decrypt(). El resultado podemos verlo a continuación:

Finalmente, la flag aparece descrifrada ante nuestros ojos.

Finalmente, la FLAG es:


Toni Castillo @disbauxes

Labview 2015 NI Instrument Driver Finder complains about not being connected to the Internet


Whenever trying to use the “IDFinder” Labview 2015 facility on an old Windows XP computer, after a couple of seconds trying an error dialog message pops up saying: “NI Instrument Driver Finder has encountered problems connecting to the instrument driver network. Please verify that your computer is connected to the internet and try again.” The computer is connected to the Internet and it can browse the NI website by using a regular Internet browser.

Capturing some traffic

We re-route all the traffic from that client computer to a GNU/Linux laptop running Wireshark, capturing all the traffic generated when the user clicks on the Driver Finder menu option to show the IDFinder window until LabView shows the error:

1 0.000000000 SSLv2 Client Hello
2 0.167900000 TLSv1.2 Alert (Level: Fatal, Description: Protocol Version)
3 0.168016000 TCP https→argis-te [RST, ACK] Seq=8 Ack=82 Win=9811 Len=0

 So according to the previous capture, Labview tries to connect to the NI server ( through an HTTPs connection using the SSLv2 protocol (frame: 1). Next, the NI server sends an ALERT message because it does not allow the connection to be established due to this vulnerable protocol version (frame: 2). Finally, the NI server ReSeTs the connection and LabView throws the “connection error” message (frame: 3).

Supported Windows XP HTTPs protocols

According to this:, Windows XP does have support for TLS v1.0, but not for TLS v1.1 or TLS v1.2. Of course TLS v1.0 is vulnerable, and no server should be using it. But still. So we enumerate which TLS protocols the NI server supports:

~$ nmap –script=ssl-enum-ciphers.nse -p443
443/tcp open https
| ssl-enum-ciphers:
| TLSv1.0:
| TLSv1.1:
| TLSv1.2:

Perfect; it does have support for TLS v1.0. So the problem here is that LabView is using SSLv2 instead of TLS v1.0 on the Windows XP computer. LabView uses IE API behind the scenes in order to connect to the NI website, so it seemed obvious that the issue could be solved by ensuring that IE had the “Use TLS v1.0” option enabled. We went to “Control Panel / Internet Options” and the “Use TLS v1.0” was unchecked. We enabled it and tried again; this time the IDFinder worked perfeclty fine. So far, because at some point we expect NI to remove TLS v1.0 and TLS v1.1 protocols altogheter.

My suggestions have been clear: time to retire that old Windows XP computer and use a newer one, with at least an OS that has yet to reach its EOL.

Some comments on TLS/XP

Now the worrying thing about it all. We do know Windows XP is like a gruyere cheese, full of holes. We do know neither TLS v1.0 nor TLS v1.1 should be used. But hey! They still are. There are hundreds of Windows XP computers out there, because they cannot be replaced with modern hardware. And there are thousands of websites still running on TLS v1.0 and TLS v1.1. NI server should NOT be using TLS v1.0 or TLS v1.1, and our laboratory should NOT be using a Windows XP computer. Suffice is to say that shit happens. Full stop.