Pexpect – automating terminal: <SSH, Telnet, Wireshark, w3af>

Pexpect is a Python module that works like Unix's expect library. The primary purpose of this library is to automate interactive console commands and utilities. Pexpect is a pure Python module for spawning child applications, controlling them, and responding to expected patterns in their output. Pexpect allows your script to spawn a child application and control it as if a human were typing commands. Pexpect can be used for automating interactive applications such as SSH, FTP, passwd, Telnet, and so on.

We will be using Pexpect to automate Metasploit with Python and also in to invoke various use-cases of terminal automation that require user interaction. It must be noted that there are two other methods for invoking Metasploit with Python code: "msfrpc", which calls the service API built on top of Metasploit, and ".rc" scripts. We have observed maximum success, however, using the Pexpect module.

The Pexpect module has a spawn class that is used to spawn any terminal command, process, or tool. The tools that are spawned should be spawned as a child process of the code.

The syntax for the spawn class constructor is as follows:

pexpect.spawn(command, args=[], timeout=30, maxread=2000, searchwindowsize=None, logfile=None, cwd=None, env=None, ignore_sighup=False, echo=True, preexec_fn=None, encoding=None, codec_errors='strict', dimensions=None, use_poll=False)

The spawn class constructor takes many parameters, but the mandatory one is command. The command is the actual command that we wish to execute on a Unix terminal. If we wish to pass arguments to the command invoked, we can either specify the arguments with the command itself, separated with a space, or pass the arguments as a Python list specified under the second argument args. The third argument is timeout, which is 30 seconds by default. This implies that if a process is not spawned within 30 seconds, the whole operation will be terminated. If our server is under a high load, or we have performance issues, we can increase the timeout parameter. The following code represents how to invoke an SSH session with Pexpect:

child = pexpect.spawn('/usr/bin/ftp')
child = pexpect.spawn('/usr/bin/ssh [email protected]')

We can also construct it with a list of arguments as follows:

child = pexpect.spawn('/usr/bin/ftp', [])
child = pexpect.spawn('/usr/bin/ssh', ['[email protected]'])

When the command is executed on the terminal, a session is created and controlled via the process, which is returned and placed under the child variable, as shown in the preceding example.

Another important class for pexpect is expect. Expect, as the name suggests, lays down the expected output or outputs that might be produced if the spawn command is executed successfully. For example, if the spawn command is pexpect.spawn('/usr/bin/ssh',['[email protected]']), we would usually expect the ssh server to ask us for a password. All the possible patterns or strings that might be expected from the previously specified command are passed as arguments to the pexpect.expect class, and if any of the patterns match, we can define the next command to be sent to the terminal according to the match. If there is no match, we may abort the operation and try to debug it.

The following syntax looks through the stream until a pattern is matched. The pattern is overloaded and may take several types. The pattern can be a String Type, EOF, a compiled regular expression, or a list of any of those types:

pexpect.expect(pattern, timeout=-1, searchwindowsize=-1, async_=False, **kw)

If you pass a list of patterns and more than one matches, the first match in the stream is chosen. If more than one pattern matches at this point, the leftmost pattern in the pattern list is chosen. For example:

# the input is 'foobar'
index = p.expect(['bar', 'foo', 'foobar'])
# returns 1('foo') even though 'foobar' is a "better" match

child.sendLine(command) is a method that takes the command that is to be sent to the terminal assuming everything is working as per the expected pattern:

child = pexpect.spawn('scp foo [email protected]:.')
child.expect('Password:')
child.sendline(mypassword)

Let's take a small example of SSH automation using Pexpect that will make things clearer:

child = pexpect.spawn(ssh [email protected])
i=child.expect(['.*Permission denied.*', 'root@.* password:.*','.* Connection refused','.*(yes/no).*',pexpect.TIMEOUT,'[#$]',pexpect.EOF],timeout=15)
if(i==1):
child.sendline('root')
j=child.expect(['root@.* password:.*', '[#$] ','Permission denied'],timeout=15)
if(j==1):
self.print_Log( "Login Successful with password root")
else:
self.print_Log("No login with pw root")

In the preceding code, we are taking only the success scenario. It must be noted that if the terminal expects what lies at index 1 of the input list 'root@.* password:.', then we pass the password as root with the help of the sendline method. Note that 'root@.* password:.' indicates any IP address after root, because it is a regex pattern. Based on the index of the string/regex pattern matched, we can formulate our logic to indicate what should be done next.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset