Expect Scripting
Written by bcopos on July 26, 2014.
Expect is an extension of the Tcl scripting language that allows a user to automate their interaction with a program's terminal interface. It is often used to automate ssh scripts or even the creation of keys or other tasks. In my case, I am using Expect to script the interaction with a fuzzer and remote program (via SSH).
What?
My task was to run a fuzzer on a program that resided inside a virtual machine guest. The program was a simple echo
server. Once executed, the user is presented with a prompt where they can provide input. The program would then repeat the input to stdout.
For the fuzzer, after looking at many open choices available, I decided to go with zzuf . My decision to go with this fuzzer was based both on its simplicity and small learning curve as well as its features which fit well with my needs.
How?
At first, I imagined that this task would be rather trivial and straight-forward. One can easily run a command on a remote VM using something along the lines of ssh [host] '[command]'
. Using that command, I could run the program that resides inside the guest from the host. Once I ran that command, I was presented with the prompt and I could interact with the program as if it was running locally. Great, no problem... yet. Incorporating the fuzzer wasn't a difficult task either. zzuf has a flag which enables fuzzing of input from stdin. It essentially captures user input before redirecting it to the program. Therefore, using zzuf -i ssh [host] 'command'
I was able to interact with the program and have my input be fuzzed.
The difficulty came in when I wanted to automate this process. I essentially had two options. I could write a simple bash script which runs that command repeadetly and have echo send a string (or redirect a file as input) or I could learn and use Except scripting. Why not just use the bash script? Overhead. Arguably it isn't significant and it doesn't really matter, but this gave me an excuse to learn something new. Using the Except script below I was able to automate the interaction with the program and use only one program execution to test a number of fuzzed inputs.
#!/bin/bash
spawn /bin/bash -c zzuf -i [other options] ssh [host] -p [port] '/path/to/binary'
set ITERATIONS 1000
set c 0
set timeout 0.1
sleep 1 # wait for remote program to start
while {$c < $ITERATIONS} {
expect "*.*"
sleep 0.1
send "AAAAAA"
expect "*.*"
}