Copy Link
Add to Bookmark
Report

Xine - issue #4 - Phile 111

eZine's profile picture
Published in 
Xine
 · 6 months ago

 
/-----------------------------\
| Xine - issue #4 - Phile 111 |
\-----------------------------/

automating things with expect
by b0z0/ikx


this text wants to be a very small introduction to expect, a very nice tcl
extension that helps you automating scripts that do need interaction with
other programs. with some basic knowledge of tcl you can actually create
very funny tasks with expect without having to write from scratch things
that are already supplied from other system programs or whatever. this can
be of course very useful to automatize scanning and breaking-in for very
common exploits or something like that. and, yes, what is important to say
is that this language is quite portable, since tcl with expect nowadays
runs on a very large number of unix like operatings systems and i think on
windozes too (but i'm not sure, haven't checked... i mean, i just don't
care about windoze anyway). but first of all what is expect:
it is a tcl extension, that contains some functions that make the
interaction of your script with other programs very easy. of course, since
it is based on tcl you need to know tcl to actually do something with a
tcl extension (you argued that before probably?) like expect. you won't
find a full tutorial in the next part of the text, but rather a very fast
overview of some basic things that may make you approach this language and
write fastly some easy scripts. for more informations get a good tcl
book/tutorial from somewhere or just read some manpages. most of the
things will be introduced by examples, which i think is a very fast way to
learn such an easy language.

let's begin, first of all, let's see how variables are handled. variables
don't need to be declared at some place and you don't need to declare
which type they are. tcl will just do the necessary conversions of
variables for you depending on operations you need to execute. so you can
just think on everything being a string and when you will be going to make
some arithmetics the interpreter will convert them to integer or whatever.
so the usual sample:


set ovar "world sux"
puts $ovar


the set command as you could argue is used to assign some value to a
variable (named ovar in our example) which takes as arguments the variable
name and its value. the second line will then display the variable value.
you can now notice that when you prepend the dollar ($) symbol at the
variable name you'll get the variable value. let's continue with the tcl
syntax. it is very important the use of the brackets and braces. things
included in brackets "[]" are interpreted like commands which value will
be inserted instead of them. you could compare this to the "``" quotes
under bash. the braces "{}" instead are used to unite the internal
contents. so by examples:


set ovar 36
set newvar [expr $ovar * 2]
set secvar {expr $ovar * 2}


so newvar will finally contain the value 72, that is $ovar * 2, while
secvar will contain the string "expr $ovar * 2". here we saw another new
command, expr. it just evaluates a given expression and returns its value.
let's see some conditional tests and loops now. of course there is the
normal if statement as in most hlls. shortly:


if {$somevar == 40} {puts gewd} else {puts nogood}


just put the expression you want to evalutate in the first braces and what
to do if succedes in the second and if needed an alternativa after the
else. as for the math and logical operators they are somewhat simillar to
c ones (do a man expr for a list of all of them with precedence). very
simillary you have the while, for and switch structures aswell. just by
some samples:


puts {meltdown countdown}
for {set count 10} {$count} {incr count -1} {
puts $count
sleep 1
}
puts {i don't care}

puts {meltdown countdown}
set count 10
while {$count > 0} {
puts $count
incr count -1
sleep 1
}
puts {finally}


you should have learned the incr command aswell now. simply it takes the
variable to increment and the value the variable has to be incremented of.
we have now all the strings functions of course, various comparations,
comparations, searches, calculations and what you could think of. go read
the tcl manpage about 'string' for a full list and description of all of
them, it is just boring copy-n-pasting. you have also the usual support
for arrays of course. what we'll look a little closer, since we use thins
in the final example program, are lists. this is very used since you will
get the command line arguments, that is the argv, in a list structure,
where the element 0 is actually the first passed parameter (and not the
program name like usual with argv). let's see by examples:


set thelist [list el1 el2 el3 el4]
set firstel [lindex $thelist 0]
set thirdel [lindex $thelist 2]
lappend thelist el5
set thelist [lreplace $thelist 1 2 new23]

foreach element $thelist {puts $element}

set theip 193.31.41.2
set iplist [split $theip .]
set reip [join $iplist .]


let's examine now the examples. we first just create, using the command
list, a list called thelist that contains four elements (el1, el2, el3,
el4). we then put in the variable firstel the first element of the list.
this is actually returned by the function lindex that gives the element
numbered by the second parameter from the list given as the first
parameter. in the same way we put the third element, el3, in the variable
thirdel. we then append, with the lappen command, a new element to our
list. next we replace two elements, the second and third one with a new
one, new23. this is achieved using the lreplace function. this works on
the list given as the first parameter and replaces all the elements
starting from the index given as the second parameter up to the index
given as the third parameter with the contents of the fourth parameter. of
course to replace just one element just put the starting and ending value
of replacing to be the same. pay attention that lreplace doesn't work
directly on the list, like for example lappend, so it returns a new list
with the replaced element. so if you want to keep the changes in your list
you must do something like in the example, using a set before with the
substitution brackets. the next is an even simpler example, how to examine
all the list elements with a foreach. it is too clear to write more about
it, if you can't understand what it does you'd better be doing something
else. continuing with list examples we then have a split, like the split
function in perl, that splits a string, using the given delimiter, into a
list. the same way you can join some list into a string with the join
function. more about lists in manpages of course. now we came more or less
at the end of this very compact introduction to tcl. of course there is a
lot more to know, but it wasn't my goal to teach everything about tcl. you
can work with files, with sockets, using regular expressions and whatever
you would like to do that you could in another hll. using tk you can also
fastly develope an easy interface for x. well...

let's look now at the most interesting part, that is at the expect
extension. this extension is actually composed or three main functions,
expect, spawn and send. the expect function actually reads some
interactive program output and makes some actions if a desired input was
received. the spawn function, as the name says, starts a program with some
given parameters which output can be then checked by expect. the send
function finally sends interactive input to the program we are talking to.
there are plenty of options and particularities for this three functions
(rtfm!) but we will just proceed with some samples:


set timeout 5
set users [list jesus christ me]
spawn telnet mailhost.com 25
expect {
"ESMTP" {}
timeout {exit}
}
foreach check $users {
send "EXPN $check\r"
sleep 1
}
expect eof


here we first declare a list of user we would like to do EXPN about. we
spawn then a normal telnet at some host on the smtp port. once we got the
ESMTP string, that should tell us a good connection was done, we send the
EXPN for each user we want to. finally we wait for the connection to be
closed (if we get an eof or if the timeout expires). the timeout is
actually carried in the timeout variable and is by default 10 seconds.
one more sample, an automatized login over a telnet:


set user 36degrees
set pass borntodie
set timeout 4
log_user 0
stty -echo

spawn telnet smarthost.com 23
expect {
"Last login:" {}
"ogin:" {send "$user\r"; exp_continue}
"ssword:" {send "$pass\r"; exp_continue}
"incorrect" {puts "bad password supplied!\n"; exit}
timeout {puts "timed out"; exit}
}
interact


let's examine this one, we first set some variables like username and
password we are gonna use. the "log_user 0" line means that the output of
the expect session, that is the various prompts and command sent, won't be
displayed. this is to make the solution neater. simillary the "stty -echo"
won't display characters the user should try to type in during the
execution (like when you type the password at your login). the sample
script will then start a telnet session and then will expect a few things.
if the line received contains a "Last login:" then we could argue we got
in the site, so we can just do nothing (that is that braces) and exit from
the expect loop. the next possible input we could get is a "ogin:", that
could be a login prompt. if so just send the user name and then continue
the expect loop (that is the exp_continue) since we should need to wait
for a password prompt aswell. when we will get the password prompt, that
is a "assword:", we will send at the same way the password and wait for a
response, either a "Login incorrect" or the beginning "Last login:". we
have just to handle the first one tho, so just add another expectation in
the braces that will display an error message and exit. if for some reason
a timeout will occour, let's tell about that and exit aswell. if a
sucessfull login was done, so we came out of the expect braces, we will
just leave the program interactively to the user, using the interact
command.

and now let's give a look to the final example for this tutorial. the code
presented below will scan a given range of ips on a given port for some
services. this was originally developed as a wingate scanner, but could be
used to check for every kind of tcp services. it takes five arguments at
the command line. the first is the starting host where to scan to, the
second is just the fourth byte of the c class of the starting host where
to stop the scanning, the third parameter is the port where to check, the
fourth is the string we are looking for and the last is a timeout for
connection. with an example:


./exscan 193.23.13.36 79 25 "8.8.6" 20


will scan the part of the c class starting from 193.23.13.36 to
193.23.13.79 on the smtp port for a string "8.8.6". this could be an
example of searching for that given version of sendmail on a serie of
machines. this script doesn't have many features, it was just written for
fun as a useful (somewhat) example for this small tutorial. it can be
easily modified to scan for b classes, to search regular expressions when
connected or whatever.


----------------------------------------------------------------------
#!/usr/bin/expect

if {$argc == 0} { puts "options: host endip port string timeout";exit }

# read some arguments
set host [lindex $argv 0]
set endip [lindex $argv 1]
set port [lindex $argv 2]
set string [lindex $argv 3]
set timeout [lindex $argv 4]

# check a bit arguments and use default values
if [expr {$endip == ""} || {$endip > 254}] { set endip 254 }
if {$port == ""} { set port 23 }
if {$string == ""} { set string "ingate>" }
if {$timeout == ""} { set timeout 10 }

# split ip in our list
set hostbytes [split $host .]

# check if ip is valid
if {[lindex $hostbytes 3] == ""} {
puts "invalid address\n"
exit
}

foreach byte $hostbytes {
if {$byte > 255 || $byte < 0} {
puts "invalid address\n"
exit
}
}

stty -echo

# loop through the desired range of ips
while {[lindex $hostbytes 3] < [expr $endip + 1] } {
log_user 0
# put the list of ip address bytes into a string
set host [join $hostbytes "."]
# start telnet
spawn -noecho telnet $host $port
# wait for output
expect {
# if got string then we founded what we were looking for
$string { puts "$host: present" }
# if timeout then our string wasn't received
timeout { puts "$host: not present" }
}
# go to next ip
set hostbytes [lreplace $hostbytes 3 3 [expr [lindex $hostbytes 3] + 1]]
}
----------------------------------------------------------------------


well, that's all for this small text file. hope it was quite clear and
that someone will find some use with this.



← previous
next →
loading
sending ...
New to Neperos ? Sign Up for free
download Neperos App from Google Play
install Neperos as PWA

Let's discover also

Recent Articles

Recent Comments

Neperos cookies
This website uses cookies to store your preferences and improve the service. Cookies authorization will allow me and / or my partners to process personal data such as browsing behaviour.

By pressing OK you agree to the Terms of Service and acknowledge the Privacy Policy

By pressing REJECT you will be able to continue to use Neperos (like read articles or write comments) but some important cookies will not be set. This may affect certain features and functions of the platform.
OK
REJECT