« BIOSが立ち上がらない。 | トップページ | vim copy & pasteでフォーマットが崩れる »

2008年3月 1日 (土)

パケットジェネレータ

ネットワークやセキュリティの試験をする際、送信するパケットのMACアドレスやIPアドレスを自由に設定できる必要がある。
そういう際によく使われるのはsmartbitという機材だが、いかんせんめちゃ高。とても個人で購入できる代物ではない。
そこで、自分のパソコンからsmartbitのように好きなパケットを流すツールがNetwork packet generator (Windows専用)というツールだ。
EthernetフレームからのデータをすべてHEX文字で設定したデータをそのまま流すことができるというスグレものなのだが、いかんせんUDPのデータを送る際にいちいちチェックサムやデータ内容をHEX文字に置き換えるのが大変面倒。
そこでNetwork packet generator用のUDPプロトコルのパケットデータを簡単に作れるrubyのプログラムを2年ぐらい前に作っていた。どうもsipのテスト用に作ったようだ。すっかり忘れていた。今だともっと簡単に,おまけにTCPも対応できそうだが、それは必要になった時に。

無保証です。問題が起こっても、保証しません。

使い方
ruby packet.rb データ記述ファイル

標準出力にNetwork packet generator用のデータが
出力される。そのため普通は >ファイル名 でリダイレクトして使う。

データ記述ファイルフォーマット
以下の順にカンマ区切りでレコードを書き、複数パケットは改行

行先MACアドレス,送信元MACアドレス,送信元IP,送信先IP,宛先ポート,送信先ポート,データ部分の内容が書かれたファイル名

packet.rb

 def makeChecksum(sumArr)
  arr = Array.new
  i = 0
  j = 0
  while i < sumArr.length
    arr[j] = sumArr[i].to_s + sumArr[i+1].to_s + sumArr[i+2].to_s + sumArr[i+3].to_s
    i=i+4
    j=j+1
  end
  hexArr = arr.collect{|c| c.hex}
  sum = 0
  idx = 0
  hexArr.each{|e|
    sum += e
    if(sum & 0x80000000)
      sum = (sum & 0xffff) + (sum >> 16)
    end
  }
  while(sum > 65535)
    sum = (sum & 0xffff) + (sum >> 16)
  end
  if(sum != 0xffff)
    sum = 65535-sum
  end
  return make2Hex(sum)
end
def makeHexStr(contents)
  hexStr=""
  count = 0
  contents.each_byte {|c|
    if(count %8 ==0)
      hexStr += "\n "
      hexStr += sprintf("%02X",c)
    else
      hexStr += sprintf(" %02X",c)
    end
    count = count+1
  }
  return hexStr
end
def make2Hex(port)
  source = sprintf("%X",port)
  sArray = source.split('')
  while sArray.length < 4
    sArray.unshift("0")
  end
  return sArray
end
def makeUdpHeader(contents,sourcePort,destinationPort)
  dm = make2Hex(destinationPort)
  sm = make2Hex(sourcePort)
  len = contents.length + 8
  lenArr = make2Hex(len)
  return dm.concat(sm).concat(lenArr).concat(["0","0","0","0"])
end
def checkMac(mac)
  if(mac.length != 12 || mac !~ /[0-9A-Fa-f]/)
    return false
  end
  return true
end

def formatIp(ip)
  ipArray = Array.new
  if(ip =~ /([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})/)
    i=1
    while i <= 4
      num = eval("$#{i}")
      if(num.to_i > 255)
        print "num format#{num}\n"
        return nil
      end
      ipArray[i-1] = sprintf("%02X",num)
      i=i+1
    end
  else
    print "not format\n"
    return nil
  end
  return ipArray
end
fn = ARGV.shift
File::open(fn){|f|
  i=1
  f.each{|line|
    values = line.split(/\s*,\s*/)
    if(values.length != 7)
      print "format error line:#{i}"
      exit
    end
    destMac,sourceMac,sourceIp,destIp,destinationPort,sourcePort,outPutFile=values;
    cf = open(outPutFile.chomp,"rb")
    if(!cf)
      print "#{outPutFile} can't open"
      exit
    end
    contents = cf.read
    cf.close
    if(!checkMac(destMac))
      print "destMac format error line:#{i}"
      exit
    end
    if(!checkMac(sourceMac))
      print "sourceMac #{sourceMac} format error line:#{i}"
      exit
    end
    dIp = formatIp(destIp)
    if(!dIp)
      print "destIp #{destIp} format error line:#{i}"
      exit
    end
    sIp = formatIp(sourceIp)
    if(!sIp)
      print "sourceIp #{sourceIp} format error line:#{i}"
      exit
    end
    if(destinationPort !~ /^\d+$/)
      print "destinationPort #{destinationPort} format error line:#{i}"
      exit
    end
    if(sourcePort !~ /^\d+$/)
      print "sourcePort #{sourcePort} format error line:#{i}"
      exit
    end

    uh = makeUdpHeader(contents,sourcePort,destinationPort)
    # ip(20) + udp(8) + contents
    size = 20+8+contents.length
    print "[0,1000]\n<sip #{i}>\n{\n"
    dmacAddr = destMac.split('')
    print " #{dmacAddr[0..1]} #{dmacAddr[2..3]} #{dmacAddr[4..5]} #{dmacAddr[6..7]} #{dmacAddr[8..9]} #{dmacAddr[10..11]}   #Destination MAC\n"
    smacAddr = sourceMac.split('')
    print " #{smacAddr[0..1]} #{smacAddr[2..3]} #{smacAddr[4..5]} #{smacAddr[6..7]} #{smacAddr[8..9]} #{smacAddr[10..11]} #Source MAC\n"
    proto = "0800".split('')
    print " #{proto[0..1]} #{proto[2..3]}     #protocol\n"
    versionType = "4500".split('')
    print " #{versionType[0..1]}      # Version / Header Length\n"
    print " #{versionType[2..3]}      # Type of Service\n"
    total = make2Hex(size)
    print " #{total[0..1]} #{total[2..3]}     # Total length\n"
    other = "000100008011".split('')
    print " #{other[0..1]} #{other[2..3]}     # Identification\n"
    print " #{other[4..5]} #{other[6..7]}     # Flags / Fragment offset\n"
    print " #{other[8..9]}      # Time to live\n"
    print " #{other[10..11]}      # Protocol\n"
    sumArr = Array.new
    sumArr.concat(versionType).concat(total).concat(other).concat(sIp).concat(dIp)
    checksum = makeChecksum(sumArr)
    print " #{checksum[0..1]} #{checksum[2..3]}     # Checksum\n"
    print " #{sIp[0]} #{sIp[1]} #{sIp[2]} #{sIp[3]}   #soruce IP\n"
    print " #{dIp[0]} #{dIp[1]} #{dIp[2]} #{dIp[3]}   #Destination IP\n"
    udpContents =  " #{uh[0..1]} #{uh[2..3]}      # Source port\n" +   
          " #{uh[4..5]} #{uh[6..7]}      # Destination port\n" +
          " #{uh[8..9]} #{uh[10..11]}      # Length\n"  +
          " #{uh[12..13]} #{uh[14..15]}      # Check sum\n"
    print udpContents
    contentsHex = makeHexStr(contents)
    print contentsHex
    print "\n}\n"
    i=i+1
  }
}

|

« BIOSが立ち上がらない。 | トップページ | vim copy & pasteでフォーマットが崩れる »

ruby」カテゴリの記事

コメント

コメントを書く



(ウェブ上には掲載しません)




トラックバック

この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/68673/40323896

この記事へのトラックバック一覧です: パケットジェネレータ:

» パケット適当サイト集 [パケットサイト]
パケットのリンク集形式のサイト情報です。の情報収集にお役立てください。 [続きを読む]

受信: 2008年3月 3日 (月) 15時59分

« BIOSが立ち上がらない。 | トップページ | vim copy & pasteでフォーマットが崩れる »