]> git.somenet.org - pub/jan/netsec2.git/blob - report/content/exercise2.tex
GITOLITE.txt
[pub/jan/netsec2.git] / report / content / exercise2.tex
1
2 \section{Exercise 2 - Task 1}
3 \subsection{Rep:2.a}
4 In order to use scapy we need to convert out pcap-ng dump to pcap.
5 \begin{verbatim}
6 $ tshark -r team15_ex21.pcapng -w team15_ex21.pcap -F pcap
7 \end{verbatim}
8
9 We are only interested in flows with more (or equal) than 400 packets, each exported as a separate pcap file.
10
11 \begin{verbatim}
12 $ ./somefilter.py | sh
13 \end{verbatim}
14
15 ./somefilter.py
16 \begin{redframe}\begin{scriptsize}\begin{verbatim}
17 #!/usr/bin/env python
18
19 from scapy.all import *
20
21 def somefilter(pcapfile):
22     flows = dict()
23     for p in PcapReader(pcapfile):
24         if IP in p:
25             src = p[IP].src
26             dst = p[IP].dst
27
28             if (src,dst) in flows:
29                 flows[(src,dst)] +=1
30             else:
31                 flows[(src,dst)] = 1
32
33     for flow,cnt in flows.items():
34         if cnt >= 400:
35             print 'tshark -r '+pcapfile+' -w "flow_'+flow[0]+'_'+flow[1]+'.pcap" -F pcap ' \
36                    + '\'ip.src == '+flow[0]+' and ip.dst == '+flow[1]+'\''
37
38 if __name__ == "__main__":
39     somefilter("team15_ex21.pcap")
40 \end{verbatim}\end{scriptsize}\end{redframe}
41
42 With Wireshark we poked around and exported the flows to csv to further investigate.
43
44 While poking around we came across an unexpected value of srcport.
45 \begin{verbatim}
46 $ ./srcfeat_power.py --input flow_114.176.157.191_221.72.61.209.csv --feature srcport
47 # 114.176.157.191,541,2,1.5469339647025981
48 \end{verbatim}
49 There seemed to be 2 different srcports, occuring nearly equally often.
50 We looked into it with Rapidminer and found a suspiciously alternating srcport jumping between \emph{\textbf{5950}} and \emph{\textbf{5960}}.
51
52 \includegraphics[width=0.6\columnwidth,keepaspectratio]{content/e21_flow_114_176_157_191_221_72_61_209_srcport.png}
53
54
55 \subsection{Rep:2.b}
56 The message is \emph{\textbf{Data acquired. Key for message (len=42 \& pkts>200): nSa123 (Scott)}}
57
58 \begin{redframe}\begin{scriptsize}\begin{verbatim}
59 #!/usr/bin/env python
60
61 import csv
62 import binascii
63
64 def somedecode(filename):
65   with open(filename, 'rb') as csvfile:
66     spamreader = csv.reader(csvfile, delimiter=',', quotechar='"')
67     header = None
68     bits = ""
69
70     for row in spamreader:
71       if header is None:
72         header = row
73         continue
74
75       if row[2] == '114.176.157.191' and row[10] == '5950':
76         bits += "0"
77       if row[2] == '114.176.157.191' and row[10] == '5960':
78         bits += "1"
79
80     bits = bits[:-(len(bits)%8)]
81     print binascii.unhexlify('%x' % int(bits, 2))
82
83 if __name__ == "__main__":
84     somedecode("flow_114.176.157.191_221.72.61.209.csv")
85 \end{verbatim}\end{scriptsize}\end{redframe}
86
87
88 \section{Exercise 2 - Task 2}
89 \subsection{Rep:2.c}
90 The message will be \emph{\textbf{rc4}} encrypted using the key \emph{\textbf{nSa123}}. Decrypt with:
91 \begin{verbatim}
92 $ openssl enc -d -rc4 -nosalt -k nSa123 -in stream.enc -out stream.txt
93 \end{verbatim}
94
95
96 \subsection{Rep:2.d}
97 Redo initial conversion like in the previous task, but also apply a filter to \emph{\textbf{only retain packets of length 42}}.
98
99 \begin{verbatim}
100 $ tshark -r team15_ex22.pcapng -w team15_ex22.pcap -F pcap 'frame.len == 42'
101 \end{verbatim}
102
103 After conversion apply a modified version of ./somefilter.py as it is pretty time consuming to manually create csv files. Especially if we keep changing parameters or fields.
104
105 \begin{verbatim}
106 $ ./somefilter.py | sh
107 \end{verbatim}
108
109 ./somefilter.py
110 \begin{redframe}\begin{scriptsize}\begin{verbatim}
111 #!/usr/bin/env python                                                                                                                                               
112                                                                                                                                                                     
113 from scapy.all import *                                                                                                                                             
114                                                                                                                                                                     
115 def somefilter(pcapfile):                                                                                                                                           
116     flows = dict()                                                                                                                                                  
117     for p in PcapReader(pcapfile):                                                                                                                                  
118         if IP in p:                                                                                                                                                 
119             src = p[IP].src                                                                                                                                         
120             dst = p[IP].dst                                                                                                                                         
121                                                                                                                                                                     
122             if (src,dst) in flows:                                                                                                                                  
123                 flows[(src,dst)] +=1                                                                                                                                
124             else:                                                                                                                                                   
125                 flows[(src,dst)] = 1                                                                                                                                
126                                                                                                                                                                     
127     for flow,cnt in flows.items():                                                                                                                                  
128         if cnt >= 200:                                                                                                                                              
129             print 'tshark -r '+pcapfile+' -w "flow_'+flow[0]+'_'+flow[1]+'.pcap" -F pcap ' \                                                                        
130                    + '\'ip.src == '+flow[0]+' and ip.dst == '+flow[1]+'\''                                                                                          
131             print 'tshark -n -r "flow_'+flow[0]+'_'+flow[1]+'.pcap" -Eheader=y -Eseparator=, -Equote=d -Tfields '\                                                  
132                    + '-e frame.number -e _ws.col.Time -e ip.src -e ip.dst -e _ws.col.Protocol -e frame.len '\                                                       
133                    + '-e _ws.col.Info -e _ws.col.dscp -e _ws.col.ipid -e _ws.col.cs -e _ws.col.srcport '\                                                           
134                    + '-e _ws.col.dstport -e _ws.col.proto > flow_'+flow[0]+'_'+flow[1]+'.csv'                                                                       
135                                                                                                                                                                     
136                                                                                                                                                                     
137 if __name__ == "__main__":                                                                                                                                          
138     somefilter("team15_ex22.pcap")                                                                                                                                  
139 \end{verbatim}\end{scriptsize}\end{redframe}
140
141 We examined the dumps and suspected the covert channel to be in the IPID fields.\\
142 After exporting the bytes into separate files we were stuck at decrypting the decoded bytes.
143
144 \begin{verbatim}
145 $ ./decode_ipid.py
146 $ openssl enc -d -rc4 -nosalt -k nSa123 -in stream_encrypted -out stream_decrypted
147 \end{verbatim}
148
149 After the hint \quote{Use the toooools!} we adapted the autocorr.py tool to not require the output parameter and wrote a shell wrapper to loop through all csv files for a given field name.
150
151 \begin{verbatim}
152 $ ./autocorr_all.sh _ws.col.ipid
153 \end{verbatim}
154
155 ./autocorr\_all.sh
156 \begin{redframe}\begin{scriptsize}\begin{verbatim}
157 #!/bin/bash                                                                                                                                                         
158                                                                                                                                                                     
159 for f in *.csv ; do                                                                                                                                                 
160     sed -e 's/,"0x[a-fA-F0-9]\{4\} (\([0-9]\+\))",/,"\1",/' -e 's/,"UDP"$/,"17"/' \
161         -e 's/,"ICMP"$/,"1"/' $f > ${f}.dehexed                                           
162     echo "$f, $1: $(../../autocorr.py --input ${f}.dehexed --field ${1})"                                                                                           
163 done                                                                                                                                                                
164 \end{verbatim}\end{scriptsize}\end{redframe}
165
166 After autocorr\_all'ing all available fields ip.proto produced an exception on one csv file. The investigation led to the addition of two new sed replace rules above.\\
167
168 After trying to extract and decode the Proto-field we finally came across the solution.
169
170 \begin{verbatim}
171 $ ./somedecode.py | openssl enc -d -rc4 -nosalt -k nSa123
172 \end{verbatim}
173
174 ./somedecode.py
175 \begin{redframe}\begin{scriptsize}\begin{verbatim}
176 #!/usr/bin/env python                                                                                                                                            
177                                                                                                                                                                  
178 import csv                                                                                                                                                       
179 import binascii                                                                                                                                                  
180                                                                                                                                                                  
181 def somedecode(filename):                                                                                                                                        
182   with open(filename, 'rb') as csvfile:                                                                                                                          
183     spamreader = csv.reader(csvfile, delimiter=',', quotechar='"')                                                                                               
184     header = None                                                                                                                                                
185     bits = ""                                                                                                                                                    
186                                                                                                                                                                  
187     for row in spamreader:                                                                                                                                       
188       if header is None:                                                                                                                                         
189         header = row                                                                                                                                             
190         continue                                                                                                                                                 
191                                                                                                                                                                  
192       if row[12] == 'ICMP':                                                                                                                                      
193         bits += "0"                                                                                                                                              
194       if row[12] == 'UDP':                                                                                                                                       
195         bits += "1"                                                                                                                                              
196                                                                                                                                                                  
197 #    print bits                                                                                                                                                  
198     #bits = bits[:-(len(bits)%8)]                                                                                                                                
199     print binascii.unhexlify('%x' % int(bits, 2))                                                                                                                
200                                                                                                                                                                  
201 if __name__ == "__main__":                                                                                                                                       
202     somedecode("flow_204.10.110.7_187.10.25.137.csv")                                                                                                            
203 \end{verbatim}\end{scriptsize}\end{redframe}
204
205 It turned out that scapy is not really suited to handle our decoding task as it would discard the frame.len information. \url{http://stackoverflow.com/questions/21752576/whole-packet-length-scapy}\\
206 This does not happen with the {\tt PcapRawReader}, so we rewrote the script.\\
207
208 Another fail was our fixation on ip.id. We tried to decode that field without looking at other possibilities.
209
210
211 \subsection{Rep:2.e}
212 The message is \emph{\textbf{Agent South was captured! Aborting operation. (Agent Scott)}}.
213
214
215 \section{Lessons learned}
216 Basically we have two semi-independent solutions for every task as the both of us had slightly different ways of doing things, but both wanted to learn how things work.