Npyscreens: Creating a UI that will run a shell command

Vera Worri
Vera Worri
Published in
4 min readJan 26, 2017

I have been trying to create a terminal based UI for my sniffer app. I have used curses, ncurses, and, now, I am trying npyscreens.

Working with Pycharm on a Mac, with Python 2.7.12 from Anaconda.

I went to the documentation and noticed they ave example codes so I copied and pasted them to play with them and see what each line actually does. Then I modified it to create this:

import npyscreen

class EavesdropForm(npyscreen.Form):
def create(self):
self.captureDurationType = self.add(npyscreen.TitleSelectOne,max_height=3, name='Capture Type', values=['Capture By Package Count', 'Capture By Time Limit'],scroll_exit=True)
self.duration = self.add(npyscreen.TitleText, name="Duration Value: " )
self.fileName = self.add(npyscreen.TitleFilename, name="Filename:" )
self.capFields = self.add(npyscreen.TitleMultiSelect, max_height=4, name='Tshark Fields', values=['Info Column', 'http', 'frame Number', 'IP Address'], scroll_exit=True)
self.myDate = self.add(npyscreen.TitleDateCombo, name='Date Employed')
self.stats = self.add(npyscreen.TitleMultiSelect, max_height=5, name='Capture Statistics',
values=['Conversations', 'http', 'DNS', 'Endpoints','Follow TCP/UDP'], scroll_exit=True)


def myFunction(*args):
F = EavesdropForm(name = "Eavesdrop")
F.edit()
return "FileName " + F.fileName.value

if __name__ == '__main__':
print npyscreen.wrapper_basic(myFunction)

I want the user to be able to modify:

1) capture type (whether it is by time or packet count)

2) capture duration (what value I should attach to option 1)

3)File name (what file should I save the data to)

4) Fields for the capture

5) statistics (a statistical analysis of your choice of the data captured)

It looks like this:

The “OK” button exits the screen. So I did some experimenting and realized that the selections are returned as an array type that uses the integer corresponding to the position of the selection.

With this knowledge, I built an algo to Frankenstein the tshark command I will pass into my sniffer.

In the end, it looked like this:

import npyscreen
from Eavesdrop import eavesdrop
i=0
v = ""

captureDurationTypeDict =[' -c ',
' -a files: ' ,
' -a duration: ',
" -a filesize: "]
captureFieldsDict = {
0: ' _ws.col.Info ',
1:'http ' ,
2: ' frame.number ',
3:" ip.addr ",

}


class EavesdropForm(npyscreen.Form):
def create(self):
self.captureDurationType = self.add(npyscreen.TitleSelectOne,max_height=6, name='Capture Type', values=['Capture By Packet Count',"Capture By File Size" ,'Capture By Time Limit', "Capture By Number of Files"],scroll_exit=True)
self.duration = self.add(npyscreen.TitleText, name="Duration Value: ")
self.fileName = self.add(npyscreen.TitleFilename, name="Filename:" )
self.capFields = self.add(npyscreen.TitleMultiSelect, max_height=6, name='Tshark Fields', values=['Info Column', 'HTTP', 'frame Number', 'IP Address'], scroll_exit=True)
self.stats = self.add(npyscreen.TitleMultiSelect, max_height=6, name='Capture Statistics',
values=['Conversations', 'http', 'DNS', 'Endpoints','Follow TCP/UDP'], scroll_exit=True)
def convertToComand(type,dur,fields,filename):
v="tshark -T fields -e"
for
items in fields:
v= v + (captureFieldsDict[items])
v = v + captureDurationTypeDict[type[0]] + dur + " -w " + filename + ".pcap"
return
v


def myFunction(*args):
F = EavesdropForm(name = "Eavesdrop")
F.edit()
t= F.captureDurationType.value
val= F.duration.value
fields = F.capFields.value
name = F.fileName.value
d = name + ".pcap"
stats =F.stats.value
command = convertToComand(t,val,fields,name)
output = eavesdrop(command,d)
str(output)
return output

if __name__ == '__main__':
print (npyscreen.wrapper_basic(myFunction))

I was able to pass the command into eavesdrop along with a variable called “d” (to correspond to the file name) but, I got an error:

It seems that python is checking for the existence of the file before tshark can create it. I have two things to try off hand, I can make a file by that name (this is a band-aid over a gushing wound) or, I could try and find a way for python to find the file created by tshark.

The first one didn’t work but before I could try the second solution, I had another idea. Maybe python can just wait until the file exists.

I tired incorporating this: and it worked!

I put this into my code:

while not os.path.exists(y):
time.sleep(1)
if os.path.isfile(x):

so now the entire main eavesdrop code looks like this:

from scapy.all import *
from getHTTPHeaders import HTTPHeaders, extractText
import os
import time


# os.system("tshark -T fields -e _ws.col.Info -e http -e frame.time -e "
# "data.data -w Eavesdrop_Data.pcap -c 1000")
def eavesdrop(x,y,T):
#subprocess.Popen(x, shell=True)
z = "tshark -T fields -e _ws.col.Info -e http -e frame.time -e data.data -w Eavesdrop_Data.pcap -c 10"
subprocess.Popen(x, shell=True,stdout=subprocess.PIPE,)
p = subprocess.Popen(["cmd", "arg1"], stdout=subprocess.PIPE, bufsize=1)
with p.stdout:
for line in iter(p.stdout.readline, b''):
print line,
p.wait()
while not os.path.exists(y):
time.sleep(1)
if os.path.isfile(x):
data = y
a = rdpcap(data)
sessions = a.sessions()
carved_texts = 1
for session in sessions:
http_payload = ""
for
packet in sessions[session]:
try:
if packet[TCP].dport == 80 or packet[TCP].sport == 80:
http_payload += str(packet[TCP].payload)
except:
pass
headers = HTTPHeaders(http_payload)
if headers is None:
continue
text = extractText(headers,http_payload,T)
if text is not None:
try:
text_file = open("Output.txt", "w")
text_file.write("Payload:: " % text)
text_file.close()
except:
pass

My next problem is that when the sniffing starts happening, the npyscreen quits and the sniff takes place outside my UI. I can get around this by having to program open another UI program.

To solve this I just changed the Popen command to a call command in the main Eavesdrop.py so that line looks like this:

subprocess.call(x, shell=True,stdout=subprocess.PIPE,)

With this change the terminal says open and the output looks like this:

I do not know what the second and third command are. But the screen stays on until you exit yourself. The user can control the sniff and choose the pcap file the data is saved to. Next, I will try and package it into an executable app… maybe.

--

--