Friday, April 27, 2012

Solving Network Forensics Challenges with Bro :: Part 2

Solving Network Forensic Challenges with Bro :: Part 2


1 Expanding on Part 1

In part 1, we tried to answer as many questions as we could with trial and error. In part 2 we're going to take a look at a couple of useful events and dig a little more into what Bro is capable of in scriptland. If you haven't had a chance to read Rob Lee's SANS Network Forensics Challenge writeup, take a moment to familiarize yourself with it.
Again, using the existing bro scripts is going to be our best bet for not only learning new things but for learning how to do them in a way that is consistent with how Bro works and the vision the devs have for it. It might be useful to take a look at what the most commonly used events might be.
mac@securityonion-Analyst:/usr/local/share/bro$ grep -hri "^\W*event" * | grep -v "bro_init\|bro_done" | sort | uniq -c | sort -rn | head -10
   24 event connection_state_remove(c: connection)
    9 event connection_established(c: connection)
    8 event connection_state_remove(c: connection) &priority=-5
    7 event http_request(c: connection, method: string, original_URI: string,
    7 event file_transferred(c: connection, prefix: string, descr: string,
    7 event connection_finished(c: connection)
    6 event protocol_violation(c: connection, atype: count, aid: count,
    5 event smtp_reply(c: connection, is_orig: bool, code: count, cmd: string,
    5 event remote_connection_closed(p: event_peer)
    5 event new_connection(c: connection)
Top of the list is the event connection_state_remove() and if it's that high it has to have some serious power behind it! Let's take a quick look at its documentation.
314 ## Generated when a connection's internal state is about to be removed from
315 ## memory. Bro generates this event reliably once for every connection when it
316 ## is about to delete the internal state. As such, the event is well-suited for
317 ## scrip-level cleanup that needs to be performed for every connection.  The
318 ## ``connection_state_remove`` event is generated not only for TCP sessions but
319 ## also for UDP and ICMP flows.
320 ##
321 ## c: The connection.
322 ##
323 ## .. bro:see:: connection_EOF connection_SYN_packet connection_attempt
324 ##    connection_established connection_external connection_finished
325 ##    connection_first_ACK connection_half_finished connection_partial_close
326 ##    connection_pending connection_rejected connection_reset connection_reused
327 ##    connection_status_update connection_timeout expected_connection_seen
328 ##    new_connection new_connection_contents partial_connection udp_inactivity_timeout
329 ##    tcp_inactivity_timeout icmp_inactivity_timeout conn_stats
330 global connection_state_remove: event(c: connection);
Well, we can see why connection_state_remove() gets so much use! Right before Bro decides to stop caring about this connection, it generates this event. Let's take a look at the using this event against the tracefile provided by SANS.
event connection_state_remove(c: connection)
  {
  print c;
  }     
[id=[orig_h=10.10.10.70, orig_p=1037/tcp, resp_h=10.10.10.10, resp_p=4445/tcp], orig=[size=0, state=1, num_pkts=1, num_bytes_ip=48], resp=[size=0, state=6, num_pkts=1, num_bytes_ip=40], start_time=1272498035.258314, duration=0.000076, service={

}, addl=, hot=0, history=Sr, uid=McumIfcvNF1, dpd=<uninitialized>, conn=[ts=1272498035.258314, uid=McumIfcvNF1, id=[orig_h=10.10.10.70, orig_p=1037/tcp, resp_h=10.10.10.10, resp_p=4445/tcp], proto=tcp, service=<uninitialized>, duration=0.000076, orig_bytes=0, resp_bytes=0, conn_state=REJ, local_orig=<uninitialized>, missed_bytes=0, history=Sr, orig_pkts=1, orig_ip_bytes=48, resp_pkts=1, resp_ip_bytes=40], extract_orig=F, extract_resp=F, dns=<uninitialized>, dns_state=<uninitialized>, ftp=<uninitialized>, http=<uninitialized>, http_state=<uninitialized>, irc=<uninitialized>, smtp=<uninitialized>, smtp_state=<uninitialized>, ssh=<uninitialized>, ssl=<uninitialized>, syslog=<uninitialized>]
[id=[orig_h=10.10.10.70, orig_p=1037/tcp, resp_h=10.10.10.10, resp_p=4445/tcp], orig=[size=0, state=1, num_pkts=1, num_bytes_ip=48], resp=[size=0, state=6, num_pkts=1, num_bytes_ip=40], start_time=1272498035.594943, duration=0.000037, service={

}, addl=, hot=0, history=Sr, uid=UX0bcKwPrg4, dpd=<uninitialized>, conn=[ts=1272498035.594943, uid=UX0bcKwPrg4, id=[orig_h=10.10.10.70, orig_p=1037/tcp, resp_h=10.10.10.10, resp_p=4445/tcp], proto=tcp, service=<uninitialized>, duration=0.000037, orig_bytes=0, resp_bytes=0, conn_state=REJ, local_orig=<uninitialized>, missed_bytes=0, history=Sr, orig_pkts=1, orig_ip_bytes=48, resp_pkts=1, resp_ip_bytes=40], extract_orig=F, extract_resp=F, dns=<uninitialized>, dns_state=<uninitialized>, ftp=<uninitialized>, http=<uninitialized>, http_state=<uninitialized>, irc=<uninitialized>, smtp=<uninitialized>, smtp_state=<uninitialized>, ssh=<uninitialized>, ssl=<uninitialized>, syslog=<uninitialized>]
[id=[orig_h=10.10.10.70, orig_p=1037/tcp, resp_h=10.10.10.10, resp_p=4445/tcp], orig=[size=0, state=1, num_pkts=1, num_bytes_ip=48], resp=[size=0, state=6, num_pkts=1, num_bytes_ip=40], start_time=1272498036.141827, duration=0.000045, service={

}, addl=, hot=0, history=Sr, uid=EKKnAEoqQO, dpd=<uninitialized>, conn=[ts=1272498036.141827, uid=EKKnAEoqQO, id=[orig_h=10.10.10.70, orig_p=1037/tcp, resp_h=10.10.10.10, resp_p=4445/tcp], proto=tcp, service=<uninitialized>, duration=0.000045, orig_bytes=0, resp_bytes=0, conn_state=REJ, local_orig=<uninitialized>, missed_bytes=0, history=Sr, orig_pkts=1, orig_ip_bytes=48, resp_pkts=1, resp_ip_bytes=40], extract_orig=F, extract_resp=F, dns=<uninitialized>, dns_state=<uninitialized>, ftp=<uninitialized>, http=<uninitialized>, http_state=<uninitialized>, irc=<uninitialized>, smtp=<uninitialized>, smtp_state=<uninitialized>, ssh=<uninitialized>, ssl=<uninitialized>, syslog=<uninitialized>]
...snip..
Something you'll notice is that, unlike new_connection(), connection_state_remove() will result in events in a different order. When using new_connection(), your script will generate events somewhat linearly with what is in the tracefile. If you use connection_state_remove() you'll see events generated after then connection has ended.
Looking at the output of the connection_state_remove() we can see that pertinent fields such as history, duration, and conn_state have been filled out for us. Using these values, we can start answering more questions from the SANS Forensic Challenge.
To get the answer to question #4, we can use a simple if statement to check for a responder port of 4444/tcp and then print the c$start_time and sum of c$start_time and c$duration.
event connection_state_remove(c: connection)
  {
  if (c$id$resp_p == 4444/tcp)
    {   
    print fmt("%s", strftime("%Y/%m/%d %H:%M:%S", c$start_time));
    print fmt("%s", strftime("%Y/%m/%d %H:%M:%S", c$start_time + c$duration));
    }   
  }
2010/04/28 19:40:00
2010/04/28 19:41:26
To start answering some of the other questions, we need to start looking at the state of a connection. Bro uses two shorthand fields that are not only handy in scriptland but also useful to understand while you're looking at logs: the history and conn_state The documentation for the two fields are below.
       ## ==========   ===============================================
40     ## conn_state   Meaning
41     ## ==========   ===============================================
42     ## S0           Connection attempt seen, no reply.
43     ## S1           Connection established, not terminated.
44     ## SF           Normal establishment and termination. Note that this is the same symbol as for state S1. 
45     ## REJ          Connection attempt rejected.
46     ## S2           Connection established and close attempt by originator seen (but no reply from responder).
47     ## S3           Connection established and close attempt by responder seen (but no reply from originator).
48     ## RSTO         Connection established, originator aborted (sent a RST).
49     ## RSTR         Established, responder aborted.
50     ## RSTOS0       Originator sent a SYN followed by a RST, we never saw a SYN-ACK from the responder.
51     ## RSTRH        Responder sent a SYN ACK followed by a RST, we never saw a SYN from the (purported) originator.
52     ## SH           Originator sent a SYN followed by a FIN, we never saw a SYN ACK from the responder (hence the connection was "half" open).
53     ## SHR          Responder sent a SYN ACK followed by a FIN, we never saw a SYN from the originator.
54     ## OTH          No SYN seen, just midstream traffic (a "partial connection" that was not later closed).
55     ## ==========   ===============================================
56     conn_state:   string          &log &optional;
...snip...
       ## Records the state history of connections as a string of letters.
71     ## For TCP connections the meaning of those letters is:
72     ##
73     ## ======  ====================================================
74     ## Letter  Meaning
75     ## ======  ====================================================
76     ## s       a SYN w/o the ACK bit set
77     ## h       a SYN+ACK ("handshake")
78     ## a       a pure ACK
79     ## d       packet with payload ("data")
80     ## f       packet with FIN bit set
81     ## r       packet with RST bit set
82     ## c       packet with a bad checksum
83     ## i       inconsistent packet (e.g. SYN+RST bits both set)
84     ## ======  ====================================================
85     ##
86     ## If the letter is in upper case it means the event comes from the
87     ## originator and lower case then means the responder.
88     ## Also, there is compression. We only record one "d" in each direction,
89     ## for instance. I.e., we just record that data went in that direction.
90     ## This history is not meant to encode how much data that happened to
91     ## be.
92     history:      string          &log &optional;
Using either of these fields we can make decisions based on the states of the connections as observed by Bro. Question #8 wants to know when the victim machine finally connected to the attacker's machine on port 4445/tcp. If you recall from the previous post, we showed that the machine attempted to connect to 4445/tcp approximately every 11 seconds or so. Since the originator made multiple attempts to connect, had we stuck with new_connection(), we would have had to store some kind of state and look for a response and session establishment between the two endpoints. Using connection_state_remove() Bro has already done the hard work for us! All we need to do is look for the state that indicates a successful connection and termination. According to the documentation for conn_state, "SF" indicates and normal connection establishment and termination.
event connection_state_remove(c: connection)
  {
  if (c$id$resp_p == 4444/tcp)
    {   
    print fmt("Start of connection to 4444/tcp: %s", strftime("%Y/%m/%d %H:%M:%S", c$start_time));
    print fmt("End of connection to 4444/tcp:   %s", strftime("%Y/%m/%d %H:%M:%S", c$start_time + c$duration));
    }   

  if (c$id$resp_p == 4445/tcp && c$conn$conn_state == "SF")
    print fmt("End of connection to 4445/tcp:   %s", strftime("%Y/%m/%d %H:%M:%S", c$start_time + c$duration));
  }
Start of connection to 4444/tcp: 2010/04/28 19:40:00
End of connection to 4444/tcp:   2010/04/28 19:41:26
End of connection to 4445/tcp:   2010/04/28 19:43:17  
It's easy to see why connection_state_remove() is used so often! In just a few minutes we were able to answer three more questions from the forensics challenge. Refactoring the code from the last post, it doesn't change our code all that much. It will, however, allow us to leverage more information as our scripting requirements expand.

2 The unbroly new_packet()

Solving questions like 7a and 7b require that we start looking at the packet level instead of at whole connections. Some short time spent grepping through the event.bif.bro file leads us to new_packet() and a warning that we should definitely respect!
479 ## Generated for every packet Bro sees. This is a very low-level and expensive
480 ## event that should be avoided when at all possible. Is's usually infeasible to
481 ## handle when processing even medium volumes of traffic in real-time. That
482 ## said, if you work from a trace and want to do some packet-level analysis,
483 ## it may come in handy.
484 ##
485 ## c: The connection the packet is part of.
486 ##
487 ## p: Informattion from the header of the packet that triggered the event.
488 ##
489 ## .. bro:see:: tcp_packet packet_contents 
490 global new_packet: event(c: connection, p: pkt_hdr);   
Using new_packet() generates a lot of overhead! Were you to use it on live traffic, you'd like as not bring your sensor to its knees as it attempts to generate an event for every new packet. For example, running a pair of test events against the evidence trace file from the challenge shows us the extra load brought to bear on Bro.
event new_connection(c: connection)
  {
  print "new connection";
  }
event new_packet(c: connection, p: pkt_hdr)
  {
  print "new packet";
  }
bro -r evidence06.pcap event_test.bro  | grep -i "new packet" | wc -l
2554
bro -r evidence06.pcap event_test.bro  | grep -i "new connection" | wc -l
123
Seeing the difference between packet level analysis and connection level analysis, we can see why the documentation in Bro includes such a warning. Let's take a look at a sample of the pkt_hdr passed to the new_packet() by looking at init-bare.bro.
 999 ## A packet header, consisting of an IP header and transport-layer header.
1000 ##
1001 ## .. bro:see:: new_packet
1002 type pkt_hdr: record {
1003   ip: ip_hdr; ##< The IP header.
1004   tcp: tcp_hdr &optional; ##< The TCP header if a TCP packet.
1005   udp: udp_hdr &optional; ##< The UDP header if a UDP packet.
1006   icmp: icmp_hdr &optional; ##< The ICMP header if an ICMP packet.
1007 };  
As you can see, much of the pkt_hdr type is a collection of other types. Since we're only interested in the IP and TCP data types for the challenge, we're going to need to identify the fields in iphdr and tcphdr respectively.
944 ## Values extracted from an IP header.
945 ##
946 ## .. bro:see:: pkt_hdr discarder_check_ip
947 type ip_hdr: record {
948   hl: count;    ##< Header length in bytes.
949   tos: count;   ##< Type of service.
950   len: count;   ##< Total length.
951   id: count;    ##< Identification.
952   ttl: count;   ##< Time to live.
953   p: count;   ##< Protocol.
954   src: addr;    ##< Source address.
955   dst: addr;    ##< Destination address.
956 };
969 ## Values extracted from a TCP header.
970 ##
971 ## .. bro:see:: pkt_hdr discarder_check_tcp
972 type tcp_hdr: record {
973   sport: port;    ##< source port.
974   dport: port;    ##< destination port
975   seq: count;   ##< sequence number
976   ack: count;   ##< acknowledgement number
977   hl: count;    ##< header length (in bytes)
978   dl: count;    ##< data length (xxx: not in original tcphdr!)
979   flags: count;   ##< flags
980   win: count;   ##< window
981 };
Once processed by Bro, pkthdr contains the pertinent information based on the Layer 4 information it observed for the packet.
new packet: [ip=[hl=20, tos=0, len=337, id=47, ttl=128, p=6, src=10.10.10.70, dst=10.10.10.10], tcp=[sport=1035/tcp, dport=8080/tcp, seq=3905816263, ack=3420183379, hl=20, dl=297, 
new packet: [ip=[hl=20, tos=0, len=40, id=9360, ttl=64, p=6, src=10.10.10.10, dst=10.10.10.70], tcp=[sport=8080/tcp, dport=1035/tcp, seq=3420183379, ack=3905816560, hl=20, dl=0, fl
new packet: [ip=[hl=20, tos=0, len=1500, id=9361, ttl=64, p=6, src=10.10.10.10, dst=10.10.10.70], tcp=[sport=8080/tcp, dport=1035/tcp, seq=3420183379, ack=3905816560, hl=20, dl=146
Question 7 wants us to determine how often the TCP initial sequence number (ISN) and IP ID change for the repeated failed connection attempts to port 4445/tcp. The pkthdr data type provides those values in p$tcp$seq and p$ip$id respectively. Dumping the contents of these values is easy and we can likely answer our questions just visually inspecting those values. So far, I don't think I've started a single script or a test without first dumping pertinent fields and seeing what kind of information I can gather and how it's going to effect the resulting script. Not only has it been good practice to solidify some of the common data structures in my mind, but it's also been a good way to keep a smooth flow between what I see in trace file and what I attempt to do in script land.
1 event new_packet(c: connection, p: pkt_hdr)
2   {
3   if (c$id$resp_p == 4445/tcp && c$history == "")
4     print fmt("new_packet(): ip_id: %s tcp sequence: %s", p$ip$id, p$tcp$seq);
5   }
You'll notice we use an if statement that matches on the responder's port and a blank c$history. What we're testing for is a packet with the SYN bit turned on which in the context of c$history would look like "S". However, it turns out that the c$history field is very aptly named! Bro will start building the c$history field only after it's seen the packet, meaning that the first time you'll see the "S" indicating that it saw an attempted SYN will be on the ACK packet being sent back to the originator. You can see this for yourself by altering if statement above to exclude the c$history test and including it in the print statement. It's a short detour but it illustrates just a tiny bit of the work being done behind the scenes for us when we handle events at a higher level.
1 event new_packet(c: connection, p: pkt_hdr)
2   {
3   if (c$id$resp_p == 4445/tcp)
4     print fmt("new_packet(): ip_id: %s tcp sequence: %s history: %s", p$ip$id, p$tcp$seq, c$history);
5   }
new_packet(): ip_id: 359   tcp_seq: 553522758   history: 
new_packet(): ip_id: 0   tcp_seq: 0   history: S
new_packet(): ip_id: 360   tcp_seq: 553522758   history: 
new_packet(): ip_id: 0   tcp_seq: 0   history: S
new_packet(): ip_id: 361   tcp_seq: 553522758   history: 
new_packet(): ip_id: 0   tcp_seq: 0   history: S
new_packet(): ip_id: 362   tcp_seq: 553800369   history: 
new_packet(): ip_id: 0   tcp_seq: 0   history: S
...snip...
new_packet(): ip_id: 597   tcp_seq: 1979373164   history: 
new_packet(): ip_id: 0   tcp_seq: 0   history: S
new_packet(): ip_id: 598   tcp_seq: 1979373164   history: 
new_packet(): ip_id: 0   tcp_seq: 1436350344   history: Sh
new_packet(): ip_id: 599   tcp_seq: 1979373165   history: Sh
new_packet(): ip_id: 24029   tcp_seq: 1436350345   history: ShA
new_packet(): ip_id: 24030   tcp_seq: 1436350349   history: ShAd
new_packet(): ip_id: 24031   tcp_seq: 1436351809   history: ShAd
new_packet(): ip_id: 600   tcp_seq: 1979373165   history: ShAd
You can see the c$history field populating itself one step behind. Of course, if we stick to using connection_state_remove this will be completely transparent to us.
Let's get back to solving the challenge. Running the script that matches based on a blank c$history gives us:
new_packet(): ip_id: 359 tcp sequence: 553522758
new_packet(): ip_id: 360 tcp sequence: 553522758
new_packet(): ip_id: 361 tcp sequence: 553522758
new_packet(): ip_id: 362 tcp sequence: 553800369
new_packet(): ip_id: 363 tcp sequence: 553800369
new_packet(): ip_id: 364 tcp sequence: 553800369
new_packet(): ip_id: 365 tcp sequence: 554100968
new_packet(): ip_id: 366 tcp sequence: 554100968
new_packet(): ip_id: 369 tcp sequence: 554100968
new_packet(): ip_id: 370 tcp sequence: 554399680
new_packet(): ip_id: 371 tcp sequence: 554399680
new_packet(): ip_id: 372 tcp sequence: 554399680
new_packet(): ip_id: 373 tcp sequence: 554670846
...snip...  
It looks like the IP ID field and the TCP sequence number are incrementing at an interval of every packet and every three packets respectively. There are 120 connection attempts to the 4445/tcp port which is somewhat unwieldy to check visually. But wait, Bro isn't here to make you do any laborious counting. We can do this in scriptland!
We'll make use of Bro's tables and sets to confirm our suspicions about the intervals. Each time we see a SYN packet heading to port 4445/tcp we'll add that packet's ip id (p$ip$id) to a set. Since sets unique, if we see compare the number of attempts against the number of members in the ipid set (using |ipid|) using a bro_done() event they should be the same if an id is never reused. For the TCP sequence number we're going to need to use a table to track the sequence numbers and count them. We'll then treat the table like a poor man's stack and make comparisons.
 1 global attempts_count: count = 0;  
 2 global ip_id: set[count];
 3 global tcp_seq: table[count] of count;
 4 
 5 event new_packet(c: connection, p: pkt_hdr)
 6   {
 7   if (c$id$resp_p == 4445/tcp && c$history == "")
 8     {
 9     ++attempts_count;
10     if (p$ip$id !in ip_id)
11       add ip_id[p$ip$id];
12     if (p$tcp$seq !in tcp_seq)
13       tcp_seq[p$tcp$seq] = 1;
14     else
15       ++tcp_seq[p$tcp$seq];
16     }
17   }
18 
19 event bro_done()
20   {
21   local sequence_check: count;
22   local div: double;
23   for (seq in tcp_seq)
24     {
25     sequence_check = tcp_seq[seq];
26     delete tcp_seq[seq];
27     for (check in tcp_seq)
28       if (sequence_check == tcp_seq[check])
29         delete tcp_seq[check];
30     }
31   div = |ip_id| / attempts_count;
32   print fmt("IP ID changes every %.2f packet.", div );
33   if (|tcp_seq| == 0)
34     print fmt("TCP sequence changes ever %d packets.", sequence_check);
35   }
IP ID changes every 1.00 packet.
TCP sequence changes ever 3 packets.

3 Wrapping up

We covered two incredibly powerful events in this post, both of which allowed us to answer more about the SANS Network Forensic challenge, but only one of those events is viable for us in production: connection_state_remove(). While the new_packet() event has primarily niche uses due to the extra load it introduces, it's handy to parse trace files and to explore more about how Bro works and everything that Bro does behind the scenes. This is the last time we're likely to be working with the basics of Bro scripting. My intention is that Part 3 will include some more practical uses of Bro's scripting language. We'll use the things we learned in Part 1 and Part 2, but we're going to try to apply it the way Bro is intended to be used. While it's been useful (and fun!) to parse through a trace file with Bro, what we've been doing isn't something that can be deployed across an enterprise and that's where Bro really shines!

4 Code so far

If you're interested in some refactored code that includes the code we used in this post, here it is with a sample output.
 1 global earliest: time;                                     
 2 global source_ports: table[port] of time;
 3 global first_contact_4444: time;
 4 global last_contact_4444: time;
 5 global first_contact_4445: time;
 6 global last_contact_4445: time;
 7 global attempts_count: count = 0;
 8 global ip_id: set[count];
 9 global tcp_seq: table[count] of count;
10 
11 event bro_init() &priority=10
12   {
13   print "SANS Forensics Challenge";
14   print "========================";
15   earliest = current_time();
16   }
17 
18 event new_packet(c: connection, p: pkt_hdr)
19   {
20   if (c$id$resp_p == 4445/tcp && c$history == "")
21     {
22     ++attempts_count;
23     add ip_id[p$ip$id];
24     if (p$tcp$seq !in tcp_seq)
25       tcp_seq[p$tcp$seq] = 1;
26     else
27       ++tcp_seq[p$tcp$seq];
28     }
29   }
30 
31 event connection_state_remove(c: connection)
32   {
33   if (c$start_time < earliest )
34     earliest = c$start_time;
35   if (c$id$orig_h == 10.10.10.70 && c$id$resp_p == 4445/tcp)
36     {
37     if (c$id$orig_p !in source_ports)
38       source_ports[c$id$orig_p] = c$start_time;
39 
40     if (c$conn$conn_state == "SF")
41       {
42       first_contact_4445 = c$start_time;
43       last_contact_4445  = c$start_time + c$duration;
44       }
45     }
46 
47   if (c$id$resp_p == 4444/tcp)
48     {
49     first_contact_4444 = c$start_time;
50     last_contact_4444 =  c$start_time + c$duration;
51     }
52   }
53 
54 event bro_done()
55   {
56   local sports: vector of port;
57   local stime: vector of time;
58   local sequence_check: count;
59 
60   for (p in source_ports)
61     {
62     sports[|sports|] = p;
63     stime[|sports|] = source_ports[p];
64     }
65 
66   for (seq in tcp_seq)
67     {
68     sequence_check = tcp_seq[seq];
69     delete tcp_seq[seq];
70     for (check in tcp_seq)
71       if (sequence_check == tcp_seq[check])
72         delete tcp_seq[check];
73     }
74 
75   sort(stime);
76   sort(sports);
77   print "Question #4:";
78   print fmt("    Start of session to 4444/tcp: %s", first_contact_4444 - earliest);
79   print "Question #5:";
80   print fmt("    End of session to 4444/tcp: %s", last_contact_4444 - earliest);
81   print "Question #7a:";
82   if (|tcp_seq| == 0)
83     print fmt("    TCP Sequence changes every %s packets.", sequence_check);
84   print "Question #7b:";
85   print fmt("    Number of attempts: %s", attempts_count);
86   print fmt("    Number of ip id: %d", |ip_id|);
87   print "Question #7c:";
88   for (j in stime)
89     print fmt("    Delta Time: %s", stime[j+1] - stime[j]);
90   print "Question #8:";
91   print fmt("    Successful connection to 4445/tcp: %s", first_contact_4445 - earliest);
92   print "Question #10:";
93   print fmt("    Connection to 4445/tcp closed: %s", last_contact_4445 - earliest);
94   print "Connection Statistics:";
95   print "======================";
96   print fmt("First Packet: %s", strftime("%Y/%m/%d %H:%M:%OS", earliest));
97   print fmt("End of Capture: %s", strftime("%Y/%m/%d %H:%M:%S", network_time()));
98   print "========================";
99   }
SANS Forensics Challenge
========================
Question #4:
    Start of session to 4444/tcp: 1.0 sec 265.0 msecs 851.0 usecs
Question #5:
    End of session to 4444/tcp: 1.0 min 27.0 secs 587.0 msecs 153.0 usecs
Question #7a:
    TCP Sequence changes every 3 packets.
Question #7b:
    Number of attempts: 120
    Number of ip id: 120
Question #7c:
    Delta Time: 11.0 secs 785.0 msecs 487.0 usecs
    Delta Time: 11.0 secs 730.0 msecs 439.0 usecs
    Delta Time: 11.0 secs 795.0 msecs 35.0 usecs
    Delta Time: 11.0 secs 735.0 msecs 993.0 usecs
    Delta Time: 11.0 secs 884.0 msecs 180.0 usecs
    Delta Time: 11.0 secs 960.0 msecs 521.0 usecs
    Delta Time: 11.0 secs 907.0 msecs 572.0 usecs
Question #8:
    Successful connection to 4445/tcp: 2.0 mins 3.0 secs 674.0 msecs 198.0 usecs
Question #10:
    Connection to 4445/tcp closed: 3.0 mins 18.0 secs 441.0 msecs 345.0 usecs
Connection Statistics:
======================
First Packet: 2010/04/28 19:39:59
End of Capture: 2010/04/28 19:43:17
========================
Date: 2012-04-27T11:24-0400
Org version 7.8.06 with Emacs version 24
Validate XHTML 1.0

No comments:

Post a Comment

Followers