added packet fuzzing
[goodfet] / client / experiments.py
1 import sys;
2 import binascii;
3 import array;
4 import csv, time, argparse;
5 import datetime
6 import os
7 from random import randrange
8 import random
9 from GoodFETMCPCAN import GoodFETMCPCAN;
10 from GoodFETMCPCANCommunication import GoodFETMCPCANCommunication
11 from intelhex import IntelHex;
12 import Queue
13 import math
14
15 tT = time
16
17
18 class experiments(GoodFETMCPCANCommunication):
19     
20     def __init__(self):
21         GoodFETMCPCANCommunication.__init__(self)
22         #super(experiments,self).__init(self)
23         self.freq = 500;
24         
25     def filterStdSweep(self, freq, low, high, time = 5):
26         msgIDs = []
27         self.client.serInit()
28         self.client.MCPsetup()
29         for i in range(low, high+1, 6):
30             print "sniffing id: %d, %d, %d, %d, %d, %d" % (i,i+1,i+2,i+3,i+4,i+5)
31             comment= "sweepFilter: "
32             #comment = "sweepFilter_%d_%d_%d_%d_%d_%d" % (i,i+1,i+2,i+3,i+4,i+5)
33             description = "Running a sweep filer for all the possible standard IDs. This run filters for: %d, %d, %d, %d, %d, %d" % (i,i+1,i+2,i+3,i+4,i+5)
34             count = self.sniff(freq=freq, duration = time, description = description,comment = comment, standardid = [i, i+1, i+2, i+3, i+4, i+5])
35             if( count != 0):
36                 for j in range(i,i+5):
37                     comment = "sweepFilter: "
38                     #comment = "sweepFilter: %d" % (j)
39                     description = "Running a sweep filer for all the possible standard IDs. This run filters for: %d " % j
40                     count = self.sniff(freq=freq, duration = time, description = description,comment = comment, standardid = [j, j, j, j])
41                     if( count != 0):
42                         msgIDs.append(j)
43         return msgIDs
44     
45     
46     def sweepRandom(self, freq, number = 5, time = 200):
47         msgIDs = []
48         ids = []
49         self.client.serInit()
50         self.client.MCPsetup()
51         for i in range(0,number+1,6):
52             idsTemp = []
53             comment = "sweepFilter: "
54             for j in range(0,6,1):
55                 id = randrange(2047)
56                 #comment += "_%d" % id
57                 idsTemp.append(id)
58                 ids.append(id)
59             print comment
60             description = "Running a sweep filer for all the possible standard IDs. This runs the following : " + comment
61             count = self.sniff(freq=freq, duration=time, description=description, comment = comment, standardid = idsTemp)
62             if( count != 0):
63                 for element in idsTemp:
64                     #comment = "sweepFilter: %d" % (element)
65                     comment="sweepFilter: "
66                     description = "Running a sweep filer for all the possible standard IDs. This run filters for: %d " % element
67                     count = self.sniff(freq=freq, duration = time, description = description,comment = comment, standardid = [element, element, element])
68                     if( count != 0):
69                         msgIDs.append(j)
70         return msgIDs, ids
71     
72     
73      # this will sweep through the given ids to request a packet and then sniff on that
74     # id for a given amount duration. This will be repeated the number of attempts time
75     
76     #at the moment this is set to switch to the next id once  a message is identified
77     def rtrSweep(self,freq,lowID,highID, attempts = 1,duration = 1, verbose = True):
78         #set up file
79         now = datetime.datetime.now()
80         datestr = now.strftime("%Y%m%d")
81         path = self.DATALOCATION+datestr+"_rtr.csv"
82         filename = path
83         outfile = open(filename,'a');
84         dataWriter = csv.writer(outfile,delimiter=',');
85         dataWriter.writerow(['# Time     Error        Bytes 1-13']);
86         dataWriter.writerow(['#' + "rtr sweep from %d to %d"%(lowID,highID)])
87         print "started"
88         #self.client.serInit()
89         #self.spitSetup(freq)
90         for i in range(lowID,highID+1, 1):
91             self.client.serInit()
92             self.spitSetup(freq)
93             standardid = [i, i, i, i]
94             #set filters
95             self.addFilter(standardid, verbose = True)
96             
97             #### split SID into different areas
98             SIDlow = (standardid[0] & 0x07) << 5;  # get SID bits 2:0, rotate them to bits 7:5
99             SIDhigh = (standardid[0] >> 3) & 0xFF; # get SID bits 10:3, rotate them to bits 7:0
100             #create RTR packet
101             packet = [SIDhigh, SIDlow, 0x00,0x00,0x40]
102             dataWriter.writerow(["#requested id %d"%i])
103             #self.client.poke8(0x2C,0x00);  #clear the CANINTF register; we care about bits 0 and 1 (RXnIF flags) which indicate a message is being held 
104             #clear buffer
105             packet1 = self.client.rxpacket();
106             packet2 = self.client.rxpacket();
107             #send in rtr request
108             self.client.txpacket(packet)
109             ## listen for 2 packets. one should be the rtr we requested the other should be
110             ## a new packet response
111             starttime = time.time()
112             while ((time.time() - starttime) < duration):
113                 packet = self.client.rxpacket()
114                 if( packet == None):
115                     continue
116                 row = []
117                 row.append("%f"%time.time()) #timestamp
118                 row.append(0) #error flag (not checkign)
119                 row.append("rtrRequest_%d"%i) #comment
120                 row.append(duration) #sniff time
121                 row.append(1) # filtering boolean
122                 for byte in packet:
123                     row.append("%02x"%ord(byte));
124                 dataWriter.writerow(row)
125                 print self.client.packet2parsedstr(packet)
126 #            packet1=self.client.rxpacket();
127 #            packet2=self.client.rxpacket();
128 #            if( packet1 != None and packet2 != None):
129 #                print "packets recieved :\n "
130 #                print self.client.packet2parsedstr(packet1);
131 #                print self.client.packet2parsedstr(packet2);
132 #                continue
133 #            elif( packet1 != None):
134 #                print self.client.packet2parsedstr(packet1)
135 #            elif( packet2 != None):
136 #                print self.client.packet2parsedstr(packet2)
137             trial= 2;
138             # for each trial
139             while( trial <= attempts):
140                 print "trial: ", trial
141                 self.client.MCPrts(TXB0=True);
142                 starttime = time.time()
143                 # this time we will sniff for the given amount of time to see if there is a
144                 # time till the packets come in
145                 while( (time.time()-starttime) < duration):
146                     packet=self.client.rxpacket();
147                     row = []
148                     row.append("%f"%time.time()) #timestamp
149                     row.append(0) #error flag (not checking)
150                     row.append("rtrRequest_%d"%i) #comment
151                     row.append(duration) #sniff time
152                     row.append(1) # filtering boolean
153                     for byte in packet:
154                         row.append("%02x"%ord(byte));
155                     dataWriter.writerow(row)
156                     print self.client.packet2parsedstr(packet)
157 #                    packet2=self.client.rxpacket();
158 #                    
159 #                    if( packet1 != None and packet2 != None):
160 #                        print "packets recieved :\n "
161 #                        print self.client.packet2parsedstr(packet1);
162 #                        print self.client.packet2parsedstr(packet2);
163 #                        #break
164 #                    elif( packet1 != None):
165 #                        print "just packet1"
166 #                        print self.client.packet2parsedstr(packet1)
167 #                    elif( packet2 != None):
168 #                        print "just packet2"
169 #                        print self.client.packet2parsedstr(packet2)
170                 trial += 1
171         print "sweep complete"
172         outfile.close()
173         
174     # This method will do generation based fuzzing on the id given in standard id
175     # dbLimits is a dictionary of the databytes
176     # dbLimits['db0'] = [low, High]
177     # ..
178     # dbLimits['db7'] = [low, High]
179     # where low is the low end of values for the fuzz, high is the high end value
180     # period is the time between sending packets in milliseconds, writesPerFuzz is the times the 
181     # same fuzzed packet will be injecetez. Fuzzes is the number of different packets to be injected
182     def generationFuzzer(self,freq, standardId, dbLimits, period, writesPerFuzz, Fuzzes):
183         print "Fuzzing on standard ID: %d" %standardId
184         self.client.serInit()
185         self.spitSetup(freq)
186         packet = [0,0,0,0,0,0,0,0]
187         #form a basic packet
188         
189         #### split SID into different regs
190         SIDlow = (standardid[0] & 0x07) << 5;  # get SID bits 2:0, rotate them to bits 7:5
191         SIDhigh = (standardid[0] >> 3) & 0xFF; # get SID bits 10:3, rotate them to bits 7:0
192         
193         packet = [SIDhigh, SIDlow, 0x00,0x00, # pad out EID regs
194                   0x08, # bit 6 must be set to 0 for data frame (1 for RTR) 
195                   # lower nibble is DLC                   
196                  packetTemp[0],packetTemp[1],packetTemp[2],packetTemp[3],packetTemp[4],packetTemp[5],packetTemp[6],packetTemp[7]]
197         
198         
199         #get folder information (based on today's date)
200         now = datetime.datetime.now()
201         datestr = now.strftime("%Y%m%d")
202         path = self.DATALOCATION+datestr+".csv"
203         filename = path
204         outfile = open(filename,'a');
205         dataWriter = csv.writer(outfile,delimiter=',');
206         #dataWriter.writerow(['# Time     Error        Bytes 1-13']);
207         #dataWriter.writerow(['#' + description])
208             
209         
210         fuzzNumber = 0;
211         while( fuzzNumber < Fuzzes):
212             #generate a fuzzed packet
213             for i in range(0,8): # for each databyte, fuzz it
214                 idx = "db%d"%i
215                 limits = dbLimits[idx]
216                 value = random.randint(limits[0],limits[1]) #generate pseudo-random integer value
217                 packet[i+5] = value
218             
219             #put a rough time stamp on the data and get all the data bytes    
220             row = [time.time(), standardId]
221             msg = "Injecting: "
222             for i in range(5,13):
223                 row.append(packet[i])
224                 msg += " %d"%packet[i]
225             print msg
226             dataWriter.writerow(row)
227             self.client.txpacket(packet)
228             #inject the packet repeatily 
229             for i in range(1,writesPerFuzz):
230                 self.client.MCPrts(TXB0=True)
231                 time.sleep(period/1000)
232             
233             
234         outfile.close()
235             
236     
237     
238