Пример #1
0
 def decode(self, state, statemgr):
     self.statemgr = statemgr
     f = state.flow
     if f.dport == 25:
         state.open(flags="rb", statemgr=self.statemgr)
         d = state.fp.readlines()
         state.close()
         dlow = [l.lower() for l in d]
         to = [l.rstrip() for l in dlow if l.find("rcpt to") >= 0]
         subject = [l.rstrip() for l in dlow if l.find("subject") >= 0]
         if len(to) == 0:
             return
         to = set(to)
         realname = "mail-message-%d" % self.count
         self.count += 1
         fn = renameFile(state, realname)
         # assume the first entry in each list is the correct one
         if len(subject) == 0:
             output = "%s -> %s, %s at %s\n\tfile: %s\n" % (
                 state.flow.src, state.flow.dst, ",".join(to),
                 self.tf(state.ts), fn)
         else:
             output = "%s -> %s, %s, subject %s, at %s\nfile: %s\n" % (
                 state.flow.src, state.flow.dst, ",".join(to),
                 " ".join(subject), self.tf(state.ts), fn)
         self.add_flow(state.ts, state.flow.src, state.flow.dst, output)
Пример #2
0
 def _renameFlow(self, state, t):
     """state is a honeysnap.flow.flow_state object, t = response or request"""
     #print "_renameFlow:state", state.fname
     rflow = freverse(state.flow)
     #print '_renameFlow:rflow   ', rflow
     rs = self.statemgr.find_flow_state(rflow)
     if rs is not None:
         if rs.decoded is not None and state.decoded is not None:
             #print "Both halves decoded"
             user_agent = "UNKNOWN"
             url = 'UNKNOWN'
             r1 = rs.decoded
             if t == 'request':
                 try:
                     url = urllib.splitquery(state.decoded.uri)[0]
                     realname = url.rsplit("/", 1)[-1]
                 except AttributeError:
                     realname = 'index.html'
                 try:
                     url = state.decoded.headers['host'] + url
                     user_agent = state.decoded.headers['user-agent']
                 except KeyError:
                     pass
                 # reverse flows to get right sense for file renaming
                 temp = rs
                 rs = state
                 state = temp
             if t == 'response':
                 url = urllib.splitquery(r1.uri)[0]
                 realname = url.rsplit("/", 1)[-1]
                 try:
                     user_agent = r1.headers['user-agent']
                     url = r1.headers['host'] + url
                 except KeyError:
                     # probably something like a CONNECT
                     pass
             if realname == '' or realname == '/' or not realname:
                 realname = 'index.html'
             fn = renameFile(state, realname)
             id, m5 = self.id.identify(state)
             outstring = "%s -> %s, %s (%s) at %s\n" % (
                 state.flow.src, state.flow.dst, url, user_agent,
                 self.tf(state.ts))
             outstring = outstring + "\tfile: %s, filetype: %s, md5 sum: %s\n" % (
                 fn, id, m5)
             self.add_flow(state.ts, state.flow.src, state.flow.dst,
                           outstring)
Пример #3
0
 def extractActive(self, state, d):
     #print "Active FTP"
     username, password = "******", "Unknown"
     # look for port lines
     m = self.activeRE.search(d)
     if m is None:
         return
     # split data into a list of lines
     lines = d.splitlines()
     iterlines = iter(lines)
     for l in iterlines:  
         m = self.userRE.search(l)
         if m:
             username = m.group(1) 
             continue 
         m = self.passRE.search(l)
         if m:
             password = m.group(1)
             continue       
         if l.find("PORT")>=0:
             try:
                 nextl = iterlines.next()
             except StopIteration:
                 return
             if nextl.find("RETR")>=0:
                 # this means the current PORT will be
                 # a data channel for a downaload
                 filename = nextl.split(" ")[1]
                 ip_port = l.split(" ")[1].split(",")
                 #ip = ".".join(ip_port[0:4])
                 port = int(ip_port[4])*256 + int(ip_port[5])
                 # now we know the ip and port of the client
                 # data channel.
                 # find the correct state
                 # it will look like the reverse flow, with a different dport
                 rflow = freverse(state.flow)
                 rflow.dport = port
                 rflow.sport = 20
                 # find the state that carries the data
                 rstate = self.statemgr.find_flow_state(rflow)
                 # rename the data file
                 if rstate is not None:
                     fn = renameFile(rstate, filename)
                     id, m5 = self.id.identify(rstate)  
                     output = "%s requested %s from %s (%s, %s) at %s\n\tfile: %s, filetype: %s, md5 sum: %s\n" % (rstate.flow.dst, filename, 
                         rstate.flow.src, username, password, self.tf(rstate.ts), fn, id, m5)
                     self.add_flow(rstate.ts, rstate.flow.src, rstate.flow.dst, output)
Пример #4
0
 def _renameFlow(self, state, t):
     """state is a honeysnap.flow.flow_state object, t = response or request"""
     #print "_renameFlow:state", state.fname
     rflow = freverse(state.flow)   
     #print '_renameFlow:rflow   ', rflow
     rs = self.statemgr.find_flow_state(rflow)
     if rs is not None:
         if rs.decoded is not None and state.decoded is not None:
             #print "Both halves decoded"
             user_agent = "UNKNOWN"
             url = 'UNKNOWN'
             r1 = rs.decoded
             if t == 'request':
                 try:           
                     url = urllib.splitquery(state.decoded.uri)[0]
                     realname = url.rsplit("/", 1)[-1] 
                 except AttributeError:
                     realname = 'index.html'
                 try: 
                     url = state.decoded.headers['host'] + url  
                     user_agent = state.decoded.headers['user-agent']
                 except KeyError:
                     pass
                 # reverse flows to get right sense for file renaming    
                 temp = rs
                 rs = state
                 state = temp
             if t == 'response':
                 url = urllib.splitquery(r1.uri)[0]
                 realname = url.rsplit("/", 1)[-1] 
                 try:              
                     user_agent = r1.headers['user-agent']
                     url = r1.headers['host'] + url 
                 except KeyError:
                     # probably something like a CONNECT
                     pass
             if realname == '' or realname == '/' or not realname:
                 realname = 'index.html' 
             fn = renameFile(state, realname)
             id, m5 = self.id.identify(state) 
             outstring = "%s -> %s, %s (%s) at %s\n" % (state.flow.src, state.flow.dst, url, user_agent, self.tf(state.ts))
             outstring = outstring + "\tfile: %s, filetype: %s, md5 sum: %s\n" %(fn,id,m5)
             self.add_flow(state.ts, state.flow.src, state.flow.dst, outstring)
Пример #5
0
 def decode(self, state, statemgr):
     self.statemgr = statemgr
     f = state.flow
     if f.dport == 25:
         state.open(flags="rb", statemgr=self.statemgr)
         d = state.fp.readlines()  
         state.close()          
         dlow = [l.lower() for l in d]  
         to = [l.rstrip() for l in dlow if l.find("rcpt to") >= 0]
         subject = [l.rstrip() for l in dlow if l.find("subject") >=0]
         if len(to) == 0:
             return     
         to = set(to)
         realname = "mail-message-%d" % self.count
         self.count +=1 
         fn = renameFile(state, realname)
         # assume the first entry in each list is the correct one
         if len(subject) == 0:    
             output = "%s -> %s, %s at %s\n\tfile: %s\n" % (state.flow.src, state.flow.dst, 
                                                             ",".join(to), self.tf(state.ts), fn)
         else:
             output = "%s -> %s, %s, subject %s, at %s\nfile: %s\n" % (state.flow.src, state.flow.dst,
                                                                 ",".join(to), " ".join(subject), self.tf(state.ts), fn)
         self.add_flow(state.ts, state.flow.src, state.flow.dst, output)
Пример #6
0
 def extractPassive(self, state, d): 
     #print "Passive FTP"  
     username, password = "******", "Unknown"
     # repr(port/256), repr(port%256)
     # first we have to find the reverse flow/state
     # from it we will extract the ip and port info
     rflow = freverse(state.flow)
     rstate = self.statemgr.find_flow_state(rflow)
     if rstate is None:
         # no reverse state, bail
         return 
     rstate.open(flags="rb", statemgr=self.statemgr)
     dchannel = rstate.fp.readlines()
     rstate.close()
     lines = d.splitlines()
     iterlines = iter(lines)
     portlines = []
     cmdlines = []
     # find all the lines from the server
     # that open a data port
     # find all the 227 lines in the data channel
     for l in dchannel:  
         m = self._227re.search(l)
         if m is not None:
             portlines.append(l)
     # find all the client lines that use
     # a data port
     for l in lines:             
         m = self.userRE.search(l)
         if m:
             username = m.group(1) 
             continue
         else:
             username = "******"
         m = self.passRE.search(l)
         if m:
             password = m.group(1)
             continue           
         else:
             password = "******"
         w = [i for i in cmds if i in l.split()[0]]
         if len(w) == 0:
             # this line doesn't contain a data command
             continue
         cmdlines.append(l)
     # zip the 2 lists together
     # should give [(227 response, Client CMD),...]
     pairs = zip(portlines, cmdlines)
     for p in pairs:
         if p[1].find("RETR") < 0:
             # not a RETR command
             continue
         m = self.portIPRE.search(p[0])
         if m is not None:
             # the last 2 items in the RE result are the port info
             info = m.group().split(",")
             p256 = int(info[-2])
             p1 = int(info[-1])
             ip = ".".join(info[0:4])
             port = 256*p256 + p1
         else:
             continue
         filename = p[1].split(" ")[1]
         rflow.sport = port
         # passive ftp transactions happen on high ports
         # so the stream extractor has not extracted the data
         # create a new stream extractor to pull the data
         p = pcap.pcap(self.options["tmpf"])
         de = tcpflow.tcpFlow(p)
         filter = "src host %s and src port %d" % (rflow.src, rflow.sport)
         de.setFilter(filter)
         de.setOutdir(self.options["output_data_directory"]+ "/%s/ftp")
         # run the flow extractor 
         de.start()
         # now find the correct state
         flows  = [f for f in de.states.getFlows() if f.isSrcSport(ip, port)]
         if len(flows) > 0:
             if len(flows) > 1:
                 print "hmmm, got more than 1 flow"
             rflow = flows[0]
         rstate = de.states.find_flow_state(rflow)
         # rename the data file
         if rstate is not None:
             fn = renameFile(rstate, filename)
             id, m5 = self.id.identify(rstate)    
             output = "%s requested %s from %s (%s, %s) at %s\n\tfile: %s, filetype: %s, md5 sum: %s\n" % (rstate.flow.dst, filename, 
                 rstate.flow.src, username, password, self.tf(rstate.ts), fn, id, m5)                
             self.add_flow(rstate.ts, rstate.flow.src, rstate.flow.dst, output)