# ------------------------------------------------------------------ # busyservers.rb Print busy servers information # usage : busyservers # # # ------------------------------------------------------------------ require 'win32ole' USAGE = "busyservers " if ARGV.length != 1 puts USAGE exit 1 end class ServerEntry attr_writer :bytesin, :bytesout, :connections attr_reader :bytesin, :bytesout, :connections def initialize (addr, port) @addr = addr @port = port @bytesin = 0 @bytesout = 0 @connections = 0 end def getkey s=@addr + "_" + @port s.squeeze end def to_s "Server #{@addr} Port #{@port} [Connections #{@connections}]\n" + " / \\ \n" + " (in) (out) \n" + " #{@bytesin} bytes\t\t#{@bytesout} bytes\n\n" end end InputFile = ARGV[0] UnsniffDB = WIN32OLE.new("Unsniff.Database") UnsniffDB.OpenForRead(InputFile) serverMap = Hash.new unknown_cnt = 0 PacketIndex = UnsniffDB.PacketIndex prevlayer=nil (0..PacketIndex.Count-1).each do |idx| pkt = PacketIndex.Item(idx) layers = pkt.Layers layers.each do |lyr| if lyr.Name == "TCP" saddr = prevlayer.FindField("Source IP") daddr = prevlayer.FindField("Dest IP") syn = lyr.FindField("SYN") ack = lyr.FindField("ACK") sport = lyr.FindField("Src Port") dport = lyr.FindField("Dest Port") keyval_1 = daddr.Value + "_" + dport.Value keyval_2 = saddr.Value + "_" + sport.Value #print "s: #{syn.Value}\ta: #{ack.Value}\n" srv_entry = serverMap[keyval_1] if srv_entry srv_entry.bytesin += pkt.Length else srv_entry = serverMap[keyval_2] if srv_entry srv_entry.bytesout += pkt.Length end end # When a SYN Segment is seen a server is accessed if syn.Value == "1 (Set)" && ack.Value == "0 (Clear)" if !srv_entry serverMap[keyval_1] = ServerEntry.new(daddr.Value, dport.Value) srv_entry = serverMap[keyval_1] end srv_entry.connections += 1 end else prevlayer = lyr end end end # all accounting has been done, just sort by totalbytes and print the servers serverArr = serverMap.values serverArr.sort! { |a,b| b.bytesin + b.bytesout <=> a.bytesin + a.bytesout } serverArr.each {|val| print val} UnsniffDB.Close()