mirror of
https://github.com/rapid7/metasploit-framework
synced 2024-11-12 11:52:01 +01:00
Merged all of the scruby patches, fixed Dot11 support with regards to RadioTap headers.
git-svn-id: file:///home/svn/framework3/trunk@5446 4d416f70-5f16-0410-b530-b9f4589650da
This commit is contained in:
parent
4ee248bf3e
commit
c3a4cda127
@ -128,8 +128,10 @@ module Exploit::Capture
|
||||
|
||||
def each_packet
|
||||
return if not self.capture
|
||||
capture.each do |packet|
|
||||
|
||||
# print_status("Link type is #{capture.datalink}")
|
||||
|
||||
capture.each do |packet|
|
||||
dec = Scruby.linklayer_dissector(capture.datalink, packet)
|
||||
|
||||
if(dec)
|
||||
|
@ -52,10 +52,6 @@ module Scruby
|
||||
end
|
||||
end
|
||||
|
||||
def method_missing(method, *args)
|
||||
Scruby.method_missing(method, *args)
|
||||
end
|
||||
|
||||
# Same as above, for fields
|
||||
def self.field(method, *args)
|
||||
|
||||
|
@ -13,11 +13,17 @@
|
||||
module Scruby
|
||||
|
||||
# Scruby version
|
||||
SCRUBY_VERSION = '0.2.1-hdm-2'
|
||||
SCRUBY_VERSION = '0.3-hdm'
|
||||
|
||||
# Completion for functions
|
||||
FUNCTIONS_LIST = %w[sendp sniff ls lsc]
|
||||
|
||||
# Link types that are not implented in Pcap
|
||||
DLT_OPENBSD = 12
|
||||
|
||||
# Pcap::DLT_IEEE802 is 6 but on my system, sniffing on ath0 return 105 as link type
|
||||
DLT_IEEE80211 = 105
|
||||
|
||||
# History
|
||||
RECORD_HISTORY = true
|
||||
|
||||
@ -31,25 +37,111 @@ module Scruby
|
||||
TIMEOUT = 1
|
||||
LOOPBACK_DEVICE_PREFIX = 'lo'
|
||||
|
||||
# If two layers are to be bound every time
|
||||
BIND_ALWAYS = ''
|
||||
|
||||
# Constants for Ethernet
|
||||
ETHERTYPE_IPv4 = 0x800
|
||||
ETHERTYPE_ARP = 0x806
|
||||
ETHERTYPE_ALL = { ETHERTYPE_IPv4 => "IPv4",
|
||||
ETHERTYPE_ARP => "ARP"}
|
||||
ETHERTYPE_ALL = { ETHERTYPE_IPv4 => 'IPv4',
|
||||
ETHERTYPE_ARP => 'ARP' }
|
||||
ETHERADDR_ANY = '00:00:00:00:00:00'
|
||||
|
||||
# Constants for ARP
|
||||
ARPTYPE_WHOAS = 1
|
||||
ARPTYPE_ISAT = 2
|
||||
ARPTYPE_RARP_REQ = 3
|
||||
ARPTYPE_RARP_RES = 4
|
||||
ARPTYPE_DYN_RARP_REQ = 5
|
||||
ARPTYPE_DYN_RARP_REP = 6
|
||||
ARPTYPE_DYN_RARP_ERR = 7
|
||||
ARPTYPE_IN_ARP_REQ = 8
|
||||
ARPTYPE_IN_ARP_REP = 9
|
||||
|
||||
ARPTYPE_ALL = { ARPTYPE_WHOAS => 'who-as',
|
||||
ARPTYPE_ISAT => 'is-at',
|
||||
ARPTYPE_RARP_REQ => 'RARP-req',
|
||||
ARPTYPE_RARP_RES => 'RARP-rep',
|
||||
ARPTYPE_DYN_RARP_REQ => 'DynRARP-req',
|
||||
ARPTYPE_DYN_RARP_REP => 'DynRARP-rep',
|
||||
ARPTYPE_DYN_RARP_ERR => 'DynRARP-err',
|
||||
ARPTYPE_IN_ARP_REQ => 'InARP-req',
|
||||
ARPTYPE_IN_ARP_REP => 'InARP-rep' }
|
||||
|
||||
ARPHWTYPE_ETHER = 1
|
||||
ARPHWTYPE_FRAME_RELAY = 15
|
||||
ARPHWTYPE_ALL = { ARPHWTYPE_ETHER => 'Ethernet',
|
||||
ARPHWTYPE_FRAME_RELAY => 'FrameRelay' }
|
||||
|
||||
ARPHWLEN_TOKEN_RING = 1
|
||||
ARPHWLEN_ETHER = 6
|
||||
ARPHWLEN_ALL = { ARPHWLEN_TOKEN_RING => 'TokenRing',
|
||||
ARPHWLEN_ETHER => 'Ethernet' }
|
||||
|
||||
ARPPROTOLEN_IPv4 = 4
|
||||
ARPPROTOLEN_IPv6 = 16
|
||||
ARPPROTOLEN_ALL = { ARPPROTOLEN_IPv4 => 'IPv4',
|
||||
ARPPROTOLEN_IPv6 => 'IPv6' }
|
||||
|
||||
# Constants for BSD loopback interfaces
|
||||
BSDLOOPBACKTYPE_IPv4 = 2
|
||||
|
||||
# Constants for IP
|
||||
IPFLAGS = %w[MF DF evil]
|
||||
|
||||
IPPROTO_ICMP = 1
|
||||
IPPROTO_TCP = 6
|
||||
IPPROTO_UDP = 17
|
||||
IPPROTO_ALL = { IPPROTO_ICMP => "ICMP",
|
||||
IPPROTO_TCP => "TCP",
|
||||
IPPROTO_UDP => "UDP" }
|
||||
IPPROTO_ALL = { IPPROTO_ICMP => 'ICMP',
|
||||
IPPROTO_TCP => 'TCP',
|
||||
IPPROTO_UDP => 'UDP' }
|
||||
|
||||
# Constants for TCP
|
||||
TCPFLAGS = %w[FIN SYN RST PSH ACK URG ECN RES]
|
||||
|
||||
# Constants for ICMP
|
||||
ICMPTYPE_ECHO = 8
|
||||
ICMPTYPE_ECHO_REQ = 8
|
||||
ICMPTYPE_ALL = { ICMPTYPE_ECHO_REQ => 'echo request' }
|
||||
|
||||
# Constants for 802.11
|
||||
DOT11TYPE_MANAGEMENT = 0
|
||||
DOT11TYPE_CONTROL = 1
|
||||
DOT11TYPE_DATA = 2
|
||||
DOT11TYPE_RESERVED = 3
|
||||
|
||||
DOT11TYPE_ALL = { DOT11TYPE_MANAGEMENT => 'Management',
|
||||
DOT11TYPE_CONTROL => 'Control',
|
||||
DOT11TYPE_DATA => 'Data',
|
||||
DOT11TYPE_RESERVED => 'Reserved' }
|
||||
|
||||
DOT11SUBTYPE_PS_POLL = 0b1010
|
||||
DOT11SUBTYPE_RTS = 0b1011
|
||||
DOT11SUBTYPE_CF_END = 0b1110
|
||||
DOT11SUBTYPE_CF_END_CF_ACK = 0b1111
|
||||
|
||||
DOT11_FC_FLAGS = %w[to-DS from-DS MF retry pw-mgt MD wep order]
|
||||
|
||||
DOT11_CAPABILITIES = %w[res8 res9 short-slot res11 res12 DSSS-OFDM res14 res15 ESS IBSS CFP CFP-req privacy short-preamble PBCC agility]
|
||||
|
||||
DOT11_ID = {0 => 'SSID', 1 => 'Rates', 2 => 'FHset', 3 => 'DSset', 4 => 'CFset', 5 => 'TIM', 6 => 'IBSSset', 16 => 'challenge', 42 => 'ERPinfo', 46 => 'QoS Capability', 47 => 'ERPinfo', 48 => 'RSNinfo', 50 => 'ESRates',221 => 'vendor',68 => 'reserved'}
|
||||
|
||||
DOT11_REASON = {0 => 'reserved',1 => 'unspec', 2 => 'auth-expired',
|
||||
3 => 'deauth-ST-leaving',
|
||||
4 => 'inactivity', 5 => 'AP-full', 6 => 'class2-from-nonauth',
|
||||
7 => 'class3-from-nonass', 8 => 'disas-ST-leaving',
|
||||
9 => 'ST-not-auth'}
|
||||
|
||||
DOT11_AUTH_ALGO = {0 => 'open', 1 => 'sharedkey'}
|
||||
|
||||
DOT11_STATUS = {0 => 'success', 1 => 'failure', 10 => 'cannot-support-all-cap',
|
||||
11 => 'inexist-asso', 12 => 'asso-denied', 13 => 'algo-unsupported',
|
||||
14 => 'bad-seq-num', 15 => 'challenge-failure',
|
||||
16 => 'timeout', 17 => 'AP-full', 18 => 'rate-unsupported'}
|
||||
|
||||
RADIOTAP_PRESENT = %w[TSFT Flags Rate Channel FHSS dBm_AntSignal dBm_AntNoise Lock_Quality TX_Attenuation dB_TX_Attenuation
|
||||
dBm_TX_Power Antenna dB_AntSignal dB_AntNoise
|
||||
b14 b15 b16 b17 b18 b19 b20 b21 b22 b23
|
||||
b24 b25 b26 b27 b28 b29 b30 Ext]
|
||||
|
||||
def self.aware_proto
|
||||
@@aware_proto
|
||||
|
@ -37,17 +37,14 @@ module Scruby
|
||||
# Dissector for Ethernet
|
||||
class Ether<Layer
|
||||
Scruby.register_dissector(self)
|
||||
def method_missing(method, *args)
|
||||
return Scruby.field(method, *args)
|
||||
end
|
||||
|
||||
attr_accessor :dst, :src, :type
|
||||
|
||||
def init
|
||||
@protocol = 'Ethernet'
|
||||
@fields_desc = [ MACField('dst', '00:00:00:00:00:00'),
|
||||
MACField('src', '00:00:00:00:00:00'),
|
||||
XShortField('type', ETHERTYPE_IPv4) ]
|
||||
@fields_desc = [ MACField('dst', ETHERADDR_ANY),
|
||||
MACField('src', ETHERADDR_ANY),
|
||||
XShortEnumField('type', ETHERTYPE_IPv4, ETHERTYPE_ALL) ]
|
||||
end
|
||||
|
||||
end
|
||||
@ -85,25 +82,21 @@ module Scruby
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# Dissector for IPv4
|
||||
class IP<Layer
|
||||
Scruby.register_dissector(self)
|
||||
def method_missing(method, *args)
|
||||
return Scruby.field(method, *args)
|
||||
end
|
||||
|
||||
attr_accessor :version, :ihl, :tos, :len, :id, :flags, :frag
|
||||
attr_accessor :ttl, :proto, :chksum, :src, :dst
|
||||
|
||||
def init
|
||||
@protocol = 'IPv4'
|
||||
@fields_desc = [ BitField("version", 4, 4),
|
||||
BitField("ihl", 5, 4),
|
||||
@fields_desc = [ BitField('version', 4, 4),
|
||||
BitField('ihl', 5, 4),
|
||||
XByteField('tos', 0),
|
||||
ShortField('len', 20),
|
||||
XShortField('id', 0),
|
||||
BitField('flags', 0, 3),
|
||||
FlagsField('flags', 0, 3, IPFLAGS),
|
||||
BitField('frag', 0, 13),
|
||||
ByteField('ttl', 64),
|
||||
ByteEnumField('proto', IPPROTO_TCP, IPPROTO_ALL),
|
||||
@ -126,15 +119,12 @@ module Scruby
|
||||
# Dissector for ICMP
|
||||
class ICMP<Layer
|
||||
Scruby.register_dissector(self)
|
||||
def method_missing(method, *args)
|
||||
return Scruby.field(method, *args)
|
||||
end
|
||||
|
||||
attr_accessor :type, :code, :chksum, :id, :seq
|
||||
|
||||
def init
|
||||
@protocol = 'ICMP'
|
||||
@fields_desc = [ ByteField('type', ICMPTYPE_ECHO),
|
||||
@fields_desc = [ ByteEnumField('type', ICMPTYPE_ECHO_REQ, ICMPTYPE_ALL),
|
||||
ByteField('code', 0),
|
||||
XShortField('chksum', 0),
|
||||
XShortField('id', 0),
|
||||
@ -152,9 +142,6 @@ module Scruby
|
||||
# Dissector for Raw
|
||||
class Raw<Layer
|
||||
Scruby.register_dissector(self)
|
||||
def method_missing(method, *args)
|
||||
return Scruby.field(method, *args)
|
||||
end
|
||||
|
||||
attr_accessor :load
|
||||
|
||||
@ -168,9 +155,6 @@ module Scruby
|
||||
# Dissector for TCP
|
||||
class TCP<Layer
|
||||
Scruby.register_dissector(self)
|
||||
def method_missing(method, *args)
|
||||
return Scruby.field(method, *args)
|
||||
end
|
||||
|
||||
attr_accessor :sport, :dport, :seq, :ack, :dataofs, :reserved
|
||||
attr_accessor :flags, :window, :chksum, :urgptr
|
||||
@ -181,9 +165,9 @@ module Scruby
|
||||
ShortField('dport', 80),
|
||||
IntField('seq', 0),
|
||||
IntField('ack', 0),
|
||||
BitField("dataofs", 5, 4),
|
||||
BitField("reserved", 0, 4),
|
||||
XByteField('flags', 0x2),
|
||||
BitField('dataofs', 5, 4),
|
||||
BitField('reserved', 0, 4),
|
||||
FlagsField('flags', 0x2, 8, TCPFLAGS),
|
||||
ShortField('window', 8192),
|
||||
XShortField('chksum', 0),
|
||||
ShortField('urgptr', 0) ]
|
||||
@ -217,9 +201,6 @@ module Scruby
|
||||
# Dissector for UDP
|
||||
class UDP<Layer
|
||||
Scruby.register_dissector(self)
|
||||
def method_missing(method, *args)
|
||||
return Scruby.field(method, *args)
|
||||
end
|
||||
|
||||
attr_accessor :sport, :dport, :len, :chksum
|
||||
|
||||
@ -263,9 +244,6 @@ module Scruby
|
||||
# Dissector for the classic BSD loopback header (NetBSD, FreeBSD and Mac OS X)
|
||||
class ClassicBSDLoopback<Layer
|
||||
Scruby.register_dissector(self)
|
||||
def method_missing(method, *args)
|
||||
return Scruby.field(method, *args)
|
||||
end
|
||||
|
||||
attr_accessor :header
|
||||
|
||||
@ -279,9 +257,6 @@ module Scruby
|
||||
# Dissector for the OpenBSD loopback header
|
||||
class OpenBSDLoopback<Layer
|
||||
Scruby.register_dissector(self)
|
||||
def method_missing(method, *args)
|
||||
return Scruby.field(method, *args)
|
||||
end
|
||||
|
||||
attr_accessor :header
|
||||
|
||||
@ -296,9 +271,6 @@ module Scruby
|
||||
# Dissector for the Prism header
|
||||
class Prism<Layer
|
||||
Scruby.register_dissector(self)
|
||||
def method_missing(method, *args)
|
||||
return Scruby.field(method, *args)
|
||||
end
|
||||
|
||||
attr_accessor :header
|
||||
|
||||
@ -353,42 +325,11 @@ module Scruby
|
||||
|
||||
end
|
||||
|
||||
=begin
|
||||
class Dot11<Layer
|
||||
Scruby.register_dissector(self)
|
||||
def method_missing(method, *args)
|
||||
return Scruby.field(method, *args)
|
||||
end
|
||||
|
||||
attr_accessor :header
|
||||
|
||||
def init
|
||||
@protocol = '802.11'
|
||||
@fields_desc = [
|
||||
BitField("subtype", 0, 4),
|
||||
BitEnumField("type", 0, 2, ["Management", "Control", "Data", "Reserved"]),
|
||||
BitField("proto", 0, 2),
|
||||
FlagsField("FCfield", 0, 8, ["to-DS", "from-DS", "MF", "retry", "pw-mgt", "MD", "wep", "order"]),
|
||||
ShortField("ID",0),
|
||||
MACField("addr1", ETHER_ANY),
|
||||
Dot11Addr2MACField("addr2", ETHER_ANY),
|
||||
Dot11Addr3MACField("addr3", ETHER_ANY),
|
||||
Dot11SCField("SC", 0),
|
||||
Dot11Addr4MACField("addr4", ETHER_ANY)
|
||||
]
|
||||
end
|
||||
|
||||
end
|
||||
=end
|
||||
|
||||
# Dissector for RIFF file format header
|
||||
class RIFF<Layer
|
||||
Scruby.register_dissector(self)
|
||||
def method_missing(method, *args)
|
||||
return Scruby.field(method, *args)
|
||||
end
|
||||
|
||||
attr_accessor :id, :size
|
||||
attr_accessor :id, :size, :headerid
|
||||
|
||||
def init
|
||||
@protocol = 'RIFF chunk'
|
||||
@ -402,11 +343,8 @@ module Scruby
|
||||
# Dissector for ANI header chunk format
|
||||
class ANI<Layer
|
||||
Scruby.register_dissector(self)
|
||||
def method_missing(method, *args)
|
||||
return Scruby.field(method, *args)
|
||||
end
|
||||
|
||||
attr_accessor :headersize, :frames, :steps, :width, :height, :bitcount, :planes
|
||||
attr_accessor :id, :size, :headersize, :frames, :steps, :width, :height, :bitcount, :planes
|
||||
attr_accessor :displayrate, :reserved, :sequence, :icon
|
||||
|
||||
def init
|
||||
@ -428,6 +366,239 @@ module Scruby
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
# Dot11 dissectors
|
||||
class RadioTap<Layer
|
||||
Scruby.register_dissector(self)
|
||||
|
||||
attr_accessor :version, :pad, :len, :notdecoded, :present
|
||||
|
||||
def init
|
||||
@protocol = 'RadioTap'
|
||||
@fields_desc = [ ByteField('version', 0),
|
||||
ByteField('pad', 0),
|
||||
FieldLenField('len', 0, 'radiotap', 's', { :adjust => -8 } ),
|
||||
FlagsField('present', 0, 32, RADIOTAP_PRESENT),
|
||||
StrLenField('radiotap', '', 'len')
|
||||
]
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
# Dot11 dissectors
|
||||
class Dot11<Layer
|
||||
Scruby.register_dissector(self)
|
||||
|
||||
attr_accessor :subtype, :type, :proto, :FCfield, :ID, :addr1, :addr2, :addr3, :SC, :addr4
|
||||
|
||||
def init
|
||||
@protocol = '802.11'
|
||||
@fields_desc = [ BitField('subtype', 0, 4),
|
||||
BitEnumField('type', DOT11TYPE_DATA, 2, DOT11TYPE_ALL),
|
||||
BitField('proto', 0, 2),
|
||||
FlagsField('FCfield', 0, 8, DOT11_FC_FLAGS),
|
||||
ShortField('ID', 0),
|
||||
MACField('addr1', ETHERADDR_ANY),
|
||||
Dot11Addr2MACField('addr2', ETHERADDR_ANY),
|
||||
Dot11Addr3MACField('addr3', ETHERADDR_ANY),
|
||||
Dot11SCField('SC', 0),
|
||||
Dot11Addr4MACField('addr4', ETHERADDR_ANY) ]
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class Dot11QoS<Layer
|
||||
Scruby.register_dissector(self)
|
||||
|
||||
attr_accessor :TID, :EOSP, :AckPolicy, :Reserved, :TXOP
|
||||
|
||||
def init
|
||||
@protocol = '802.11 QoS'
|
||||
@fields_desc = [ BitField('TID',0,4),
|
||||
BitField('EOSP',0,1),
|
||||
BitField('AckPolicy',0,2),
|
||||
BitField('Reserved',0,1),
|
||||
ByteField('TXOP',0) ]
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class Dot11Beacon<Layer
|
||||
Scruby.register_dissector(self)
|
||||
|
||||
attr_accessor :timestamp, :beacon_interval, :cap
|
||||
|
||||
def init
|
||||
@protocol = '802.11 Beacon'
|
||||
@fields_desc = [ LongField('timestamp', 0), # Bug: should be little endian
|
||||
LEShortField('beacon_interval', 0x64),
|
||||
FlagsField('cap', 0, 16, DOT11_CAPABILITIES) ]
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class Dot11Elt<Layer
|
||||
Scruby.register_dissector(self)
|
||||
|
||||
attr_accessor :ID, :len, :info
|
||||
|
||||
def init
|
||||
@protocol = '802.11 Information Element'
|
||||
@fields_desc = [ ByteEnumField('ID', 0, DOT11_ID),
|
||||
FieldLenField('len', 0, 'info', 'C'),
|
||||
StrLenField('info', '', 'len') ]
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class Dot11ATIM<Layer
|
||||
Scruby.register_dissector(self)
|
||||
|
||||
def init
|
||||
@protocol = '802.11 ATIM'
|
||||
end
|
||||
end
|
||||
|
||||
class Dot11Disas<Layer
|
||||
Scruby.register_dissector(self)
|
||||
|
||||
attr_accessor :reason
|
||||
|
||||
def init
|
||||
@protocol = '802.11 Disassociation'
|
||||
@fields_desc = [ LEShortEnumField('reason', 1, DOT11_REASON) ]
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class Dot11AssoReq<Layer
|
||||
Scruby.register_dissector(self)
|
||||
|
||||
attr_accessor :cap, :listen_interval
|
||||
|
||||
def init
|
||||
@protocol = '802.11 Association Request'
|
||||
@fields_desc = [ FlagsField('cap', 0, 16, DOT11_CAPABILITIES),
|
||||
LEShortField('listen_interval', 0xc8) ]
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class Dot11AssoResp<Layer
|
||||
Scruby.register_dissector(self)
|
||||
|
||||
attr_accessor :cap, :status, :AID
|
||||
|
||||
def init
|
||||
@protocol = '802.11 Association Response'
|
||||
@fields_desc = [ FlagsField('cap', 0, 16, DOT11_CAPABILITIES),
|
||||
LEShortField('status', 0),
|
||||
LEShortField('AID', 0) ]
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class Dot11ReassoReq<Layer
|
||||
Scruby.register_dissector(self)
|
||||
|
||||
attr_accessor :cap, :current_AP, :listen_interval
|
||||
|
||||
def init
|
||||
@protocol = '802.11 Reassociation Request'
|
||||
@fields_desc = [ FlagsField('cap', 0, 16, DOT11_CAPABILITIES),
|
||||
MACField('current_AP', ETHERADDR_ANY),
|
||||
LEShortField('listen_interval', 0xc8) ]
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class Dot11ReassoResp<Dot11AssoResp
|
||||
Scruby.register_dissector(self)
|
||||
|
||||
def init
|
||||
@protocol = '802.11 Reassociation Response'
|
||||
end
|
||||
end
|
||||
|
||||
class Dot11ProbeReq<Layer
|
||||
Scruby.register_dissector(self)
|
||||
|
||||
def init
|
||||
@protocol = '802.11 Probe Request'
|
||||
end
|
||||
end
|
||||
|
||||
class Dot11ProbeResp<Layer
|
||||
Scruby.register_dissector(self)
|
||||
|
||||
attr_accessor :timestamp, :beacon_interval, :cap
|
||||
|
||||
def init
|
||||
@protocol = '802.11 Probe Response'
|
||||
@fields_desc = [ LongField('timestamp', 0), # Bug: should be little endian
|
||||
LEShortField('beacon_interval', 0x64),
|
||||
FlagsField('cap', 0, 16, DOT11_CAPABILITIES) ]
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class Dot11Auth<Layer
|
||||
Scruby.register_dissector(self)
|
||||
|
||||
attr_accessor :algo, :seqnum, :status
|
||||
|
||||
def init
|
||||
@protocol = '802.11 Authentication'
|
||||
@fields_desc = [ LEShortEnumField('algo', 0, DOT11_AUTH_ALGO),
|
||||
LEShortField('seqnum', 0),
|
||||
LEShortEnumField('status', 0, DOT11_STATUS) ]
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class Dot11Deauth<Layer
|
||||
Scruby.register_dissector(self)
|
||||
|
||||
attr_accessor :reason
|
||||
|
||||
def init
|
||||
@protocol = '802.11 Deauthentication'
|
||||
@fields_desc = [ LEShortEnumField('reason', 1, DOT11_REASON) ]
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class Dot11WEP<Layer
|
||||
Scruby.register_dissector(self)
|
||||
|
||||
attr_accessor :iv, :keyid, :wepdata, :icv
|
||||
|
||||
def init
|
||||
@protocol = '802.11 WEP packet'
|
||||
@fields_desc = [ StrFixedLenField('iv', "\0\0\0", 3),
|
||||
ByteField('keyid', 0),
|
||||
StrField('wepdata', ''), # Bug: 4 bytes remains
|
||||
IntField('icv', 0) ]
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class LLC<Layer
|
||||
Scruby.register_dissector(self)
|
||||
|
||||
attr_accessor :dsap, :ssap, :ctrl
|
||||
|
||||
def init
|
||||
@protocol = 'LLC'
|
||||
@fields_desc = [ XByteField('dsap', 0),
|
||||
XByteField('ssap', 0),
|
||||
ByteField('ctrl', 0) ]
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# Layer bounds
|
||||
@@layer_bounds =
|
||||
{
|
||||
@ -437,6 +608,62 @@ module Scruby
|
||||
['type', ETHERTYPE_ARP, ARP]
|
||||
],
|
||||
|
||||
'RadioTap' =>
|
||||
[
|
||||
[BIND_ALWAYS, BIND_ALWAYS, Dot11]
|
||||
],
|
||||
|
||||
'Prism' =>
|
||||
[
|
||||
[BIND_ALWAYS, BIND_ALWAYS, Dot11]
|
||||
],
|
||||
|
||||
'Dot11' => [
|
||||
['type', 2, LLC],
|
||||
['subtype', 0, Dot11AssoReq],
|
||||
['subtype', 1, Dot11AssoResp],
|
||||
['subtype', 2, Dot11ReassoReq],
|
||||
['subtype', 3, Dot11ReassoResp],
|
||||
['subtype', 4, Dot11ProbeReq],
|
||||
['subtype', 5, Dot11ProbeResp],
|
||||
['subtype', 8, Dot11Beacon],
|
||||
['subtype', 9, Dot11ATIM],
|
||||
['subtype', 10, Dot11Disas],
|
||||
['subtype', 11, Dot11Auth],
|
||||
['subtype', 12, Dot11Deauth],
|
||||
],
|
||||
|
||||
'Dot11QoS' => [
|
||||
[BIND_ALWAYS, BIND_ALWAYS, LLC]
|
||||
],
|
||||
'Dot11Beacon' => [
|
||||
[BIND_ALWAYS, BIND_ALWAYS, Dot11Elt]
|
||||
],
|
||||
'Dot11AssoReq' => [
|
||||
[BIND_ALWAYS, BIND_ALWAYS, Dot11Elt]
|
||||
],
|
||||
'Dot11AssoResp' => [
|
||||
[BIND_ALWAYS, BIND_ALWAYS, Dot11Elt]
|
||||
],
|
||||
'Dot11ReassoReq' => [
|
||||
[BIND_ALWAYS, BIND_ALWAYS, Dot11Elt]
|
||||
],
|
||||
'Dot11ReassoResp' => [
|
||||
[BIND_ALWAYS, BIND_ALWAYS, Dot11Elt]
|
||||
],
|
||||
'Dot11ProbeReq' => [
|
||||
[BIND_ALWAYS, BIND_ALWAYS, Dot11Elt]
|
||||
],
|
||||
'Dot11ProbeResp' => [
|
||||
[BIND_ALWAYS, BIND_ALWAYS, Dot11Elt]
|
||||
],
|
||||
'Dot11Auth' => [
|
||||
[BIND_ALWAYS, BIND_ALWAYS, Dot11Elt]
|
||||
],
|
||||
'Dot11Elt' => [
|
||||
[BIND_ALWAYS, BIND_ALWAYS, Dot11Elt]
|
||||
],
|
||||
|
||||
'ClassicBSDLoopback' =>
|
||||
[
|
||||
['header', BSDLOOPBACKTYPE_IPv4, IP]
|
||||
@ -466,10 +693,17 @@ module Scruby
|
||||
Ether(pkt)
|
||||
when Pcap::DLT_NULL
|
||||
ClassicBSDLoopback(pkt)
|
||||
when Pcap::DLT_RAW
|
||||
when DLT_OPENBSD
|
||||
OpenBSDLoopback(pkt)
|
||||
when Pcap::DLT_PRISM_HEADER
|
||||
Prism(pkt)
|
||||
when Pcap::DLT_IEEE802
|
||||
when Pcap::DLT_IEEE802_11
|
||||
Dot11(pkt)
|
||||
when Pcap::DLT_IEEE802_11_RADIO
|
||||
RadioTap(pkt)
|
||||
when Pcap::DLT_IEEE802_11_RADIO_AVS
|
||||
RadioTap(pkt)
|
||||
when 101,
|
||||
IP(pkt)
|
||||
else
|
||||
@ -494,6 +728,23 @@ Scruby packet dissectors/types:
|
||||
Raw
|
||||
TCP
|
||||
UDP
|
||||
LLC
|
||||
ARP
|
||||
Prism
|
||||
Dot11
|
||||
Dot11Beacon
|
||||
Dot11Elt
|
||||
Dot11ATIM
|
||||
Dot11Disas
|
||||
Dot11AssoReq
|
||||
Dot11AssoResp
|
||||
Dot11ReassoReq
|
||||
Dot11ReassoResp
|
||||
Dot11ProbeReq
|
||||
Dot11ProbeResp
|
||||
Dot11Auth
|
||||
Dot11Deauth
|
||||
Dot11WEP
|
||||
|
||||
Scapy (1.2.0.1) packet dissectors/types:
|
||||
========================================
|
||||
|
@ -45,6 +45,9 @@ module Scruby
|
||||
# Retrieves the field value from a string. This may be redefined by subclasses.
|
||||
def dissect(layer, string)
|
||||
|
||||
# Preparing the packet for building
|
||||
self.pre_build()
|
||||
|
||||
part = string.unpack(self.format + 'a*')
|
||||
|
||||
# Returning if nothing could be unpacked
|
||||
@ -73,7 +76,7 @@ module Scruby
|
||||
end
|
||||
|
||||
# Converts from human to internal encoding
|
||||
# e.g. allows TCP(:sport=>'http')
|
||||
# e.g. allows TCP(:proto=>'ICMP')
|
||||
def from_human(value)
|
||||
return value
|
||||
end
|
||||
@ -84,12 +87,23 @@ module Scruby
|
||||
return value.to_s
|
||||
end
|
||||
|
||||
# Same as tuhuman() but displays more information
|
||||
# Same as to_human() but displays more information
|
||||
# e.g. "6 (TCP)" instead of "6" for IP protocol
|
||||
def to_human_complete(value)
|
||||
return value.to_s
|
||||
end
|
||||
|
||||
# Returns yes if the field is to be added to the dissectors, e.g. depending
|
||||
# on the value of another field of the layer (see Dot11*)
|
||||
def is_applicable?(layer)
|
||||
return true
|
||||
end
|
||||
|
||||
# Prepares the packet for building
|
||||
# e.g. for StrLenField, retrieves the right format size from the associated FieldLenField
|
||||
def pre_build
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# Shortcut mixins for reducing code size
|
||||
@ -103,6 +117,24 @@ module Scruby
|
||||
end
|
||||
end
|
||||
|
||||
# Shortcut mixins for reducing code size
|
||||
module FieldHumanHexEnum
|
||||
def to_human(value)
|
||||
return sprintf('0x%x', value)
|
||||
end
|
||||
|
||||
def to_human_complete(value)
|
||||
# Checking if the value is in the enumeration keys
|
||||
if @enum.keys.include?(value)
|
||||
return sprintf('0x%x', value) + ' (' + @enum[value].to_s + ')'
|
||||
|
||||
# Otherwise, just returning the value
|
||||
else
|
||||
return sprintf('0x%x', value)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Shortcut mixins for signed conversion
|
||||
module SignedValue
|
||||
|
||||
@ -147,7 +179,7 @@ module Scruby
|
||||
end
|
||||
|
||||
def to_human_complete(value)
|
||||
|
||||
puts "ok"
|
||||
# Checking if the value is in the enumeration keys
|
||||
if @enum.keys.include?(value)
|
||||
return value.to_s + ' (' + @enum[value].to_s + ')'
|
||||
@ -201,18 +233,6 @@ module Scruby
|
||||
@format = 'A' + size.to_s
|
||||
end
|
||||
|
||||
def to_net(value)
|
||||
return value.to_s
|
||||
end
|
||||
|
||||
def to_human(value)
|
||||
return value.to_s.inspect
|
||||
end
|
||||
|
||||
def to_human_complete(value)
|
||||
return value.to_s.inspect
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# Field for a set of bits
|
||||
@ -235,6 +255,7 @@ module Scruby
|
||||
|
||||
def dissect(layer, string)
|
||||
|
||||
@@bitsdone ||= 0
|
||||
# Cannot dissect if the wanted size is greater than the length of the string
|
||||
# e.g. "IP('A'*7)" should not set frag=65
|
||||
return '' if (@@bitsdone + @size)/8 > string.length
|
||||
@ -276,6 +297,9 @@ module Scruby
|
||||
end
|
||||
|
||||
def to_net(value)
|
||||
|
||||
@@bitsdone ||= 0
|
||||
|
||||
# OR'ing this value the value the previous ones
|
||||
@@byte <<= @size
|
||||
@@byte |= value
|
||||
@ -326,7 +350,7 @@ module Scruby
|
||||
|
||||
# Same as ByteEnumField, displayed in hexadecimal form
|
||||
class XByteEnumField<ByteEnumField
|
||||
include FieldHumanHex
|
||||
include FieldHumanHexEnum
|
||||
end
|
||||
|
||||
# Field for one short (big endian/network order)
|
||||
@ -350,7 +374,7 @@ module Scruby
|
||||
|
||||
# Same as ShortEnumField, displayed in hexadecimal form
|
||||
class XShortEnumField<ShortEnumField
|
||||
include FieldHumanHex
|
||||
include FieldHumanHexEnum
|
||||
end
|
||||
|
||||
# Field for a short (little endian order)
|
||||
@ -374,7 +398,7 @@ module Scruby
|
||||
|
||||
# Same as LEShortField, displayed in hexadecimal form
|
||||
class XLEShortEnumField<LEShortEnumField
|
||||
include FieldHumanHex
|
||||
include FieldHumanHexEnum
|
||||
end
|
||||
|
||||
# Field for one integer
|
||||
@ -406,7 +430,7 @@ module Scruby
|
||||
|
||||
# Same as LEIntField, displayed in hexadecimal form
|
||||
class XIntEnumField<IntEnumField
|
||||
include FieldHumanHex
|
||||
include FieldHumanHexEnum
|
||||
end
|
||||
|
||||
# Field for one integer with enumeration
|
||||
@ -446,7 +470,7 @@ module Scruby
|
||||
|
||||
# Same as LEIntField, displayed in hexadecimal form
|
||||
class XLEIntEnumField<LEIntEnumField
|
||||
include FieldHumanHex
|
||||
include FieldHumanHexEnum
|
||||
end
|
||||
|
||||
# Field for one integer (host order)
|
||||
@ -472,7 +496,7 @@ module Scruby
|
||||
|
||||
# Same as HostOrderIntEnumField, displayed in hexadecimal form
|
||||
class XHostOrderIntEnumField<HostOrderIntEnumField
|
||||
include FieldHumanHex
|
||||
include FieldHumanHexEnum
|
||||
end
|
||||
|
||||
# Field for a float (big endian/network order)
|
||||
@ -649,6 +673,203 @@ module Scruby
|
||||
|
||||
end
|
||||
|
||||
# Field for a set of flags (e.g. each bit has a label)
|
||||
class FlagsField<BitField
|
||||
|
||||
def initialize(name, default_value, size, flags)
|
||||
@name = name
|
||||
@default_value = default_value
|
||||
@format = 'B'
|
||||
@flags = flags
|
||||
|
||||
# Number of bits in the field
|
||||
@size = size
|
||||
|
||||
# Number of bits processed so far within the current byte (class/static variable)
|
||||
@@bitsdone = 0
|
||||
|
||||
# Byte being processed (class/static variable)
|
||||
@@byte = 0
|
||||
end
|
||||
|
||||
def from_human(value)
|
||||
|
||||
return value if not value.is_a?(String)
|
||||
|
||||
# Run through the flags and set the corresponding bit if it matches
|
||||
out = 0
|
||||
@flags.length.times do |index|
|
||||
out |= 2**index if value.include?(@flags[index])
|
||||
end
|
||||
|
||||
return out
|
||||
end
|
||||
|
||||
def to_human_complete(value)
|
||||
|
||||
loops = 0
|
||||
out = ''
|
||||
|
||||
begin
|
||||
bit = value & (2**loops)
|
||||
out = @flags[loops] + ' ' + out if bit != 0
|
||||
loops += 1
|
||||
end until loops == @size
|
||||
|
||||
# Removing the last space
|
||||
out = out[0, out.length - 1] if out.length > 0
|
||||
|
||||
return value.to_s + ' (' + out + ')'
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# Field for one long (big endian/network order)
|
||||
class LongField<Field
|
||||
def init
|
||||
@format = 'Q'
|
||||
end
|
||||
end
|
||||
|
||||
# Same as LongField, displayed in hexadecimal form
|
||||
class XLongField<LongField
|
||||
include FieldHumanHex
|
||||
end
|
||||
|
||||
# Field for one long (big endian/network order) with enumeration
|
||||
class LongEnumField<EnumField
|
||||
def init
|
||||
@format = 'n'
|
||||
end
|
||||
end
|
||||
|
||||
# Same as LongEnumField, displayed in hexadecimal form
|
||||
class XLongEnumField<LongEnumField
|
||||
include FieldHumanHexEnum
|
||||
end
|
||||
|
||||
# Field that holds the length of a subsequent field
|
||||
class FieldLenField<IntField
|
||||
|
||||
def initialize(name, default_value, length_of, format, opts={})
|
||||
@name = name
|
||||
@default_value = default_value
|
||||
@format = format
|
||||
@length_of = length_of
|
||||
@opts = opts
|
||||
|
||||
# Length of the other field (class/static variable)
|
||||
@@length = {}
|
||||
|
||||
# Saving the size of the associated field
|
||||
@@length[@length_of] = @default_value
|
||||
end
|
||||
|
||||
def from_net(value)
|
||||
@opts ||= {}
|
||||
value[0] = (value[0].to_i + @opts[:adjust].to_i)
|
||||
|
||||
# Saving the size of the associated field
|
||||
@@length[@length_of] = value[0]
|
||||
end
|
||||
|
||||
def to_net(value)
|
||||
@opts ||= {}
|
||||
# value -= @opts[:adjust].to_i
|
||||
|
||||
[ value ].pack(@format)
|
||||
end
|
||||
end
|
||||
|
||||
# Field holding a string whose size is given by a previous FieldLenField
|
||||
# NB : in Scapy, the third field is a lambda-function indicating how to compute the value.
|
||||
# This is not implemented in Scruby yet.
|
||||
class StrLenField<FieldLenField
|
||||
|
||||
def initialize(name, default_value, length_from)
|
||||
@name = name
|
||||
@default_value = default_value
|
||||
@length_from = length_from
|
||||
@size = @@length[name]
|
||||
@format = 'a' + @size.to_s
|
||||
end
|
||||
|
||||
def pre_build
|
||||
@size = @@length[@name]
|
||||
@format = 'a' + @size.to_s
|
||||
end
|
||||
|
||||
def to_net(value)
|
||||
|
||||
@size = @@length[@name]
|
||||
@format = 'a' + @size.to_s
|
||||
|
||||
# By default, value is ''
|
||||
if value
|
||||
return value[0, @size].to_s
|
||||
else
|
||||
return ''
|
||||
end
|
||||
end
|
||||
|
||||
def from_net(value)
|
||||
value[0]
|
||||
end
|
||||
|
||||
def to_human(value)
|
||||
return value.inspect
|
||||
end
|
||||
|
||||
def to_human_complete(value)
|
||||
return value.inspect
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# NB for Dot11* fields:
|
||||
# These functions have different 'is_applicable?' methods, to build different
|
||||
# kinds of packets with the same dissector, depending on its type.
|
||||
# http://trac.secdev.org/scapy/ticket/4 (second point)
|
||||
# http://sss-mag.com/pdf/802_11tut.pdf
|
||||
|
||||
# Field for a 802.11 address field
|
||||
class Dot11AddrMACField<MACField
|
||||
end
|
||||
|
||||
# Field for a 802.11 address field #2
|
||||
class Dot11Addr2MACField<MACField
|
||||
def is_applicable?(layer)
|
||||
if layer.type == DOT11TYPE_CONTROL
|
||||
should = [DOT11SUBTYPE_PS_POLL, DOT11SUBTYPE_RTS, DOT11SUBTYPE_CF_END, DOT11SUBTYPE_CF_END_CF_ACK]
|
||||
return should.include?(layer.subtype)
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Field for a 802.11 address field #3
|
||||
class Dot11Addr3MACField<MACField
|
||||
def is_applicable?(layer)
|
||||
return true if layer.type == DOT11TYPE_MANAGEMENT or layer.type == DOT11TYPE_DATA
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
# Field for a 802.11 address field #4
|
||||
class Dot11Addr4MACField<MACField
|
||||
def is_applicable?(layer)
|
||||
return true if layer.type == DOT11TYPE_DATA and layer.FCfield & 0x3 == 0x3
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
# Field for a 802.11 SC field
|
||||
class Dot11SCField<LEShortField
|
||||
def is_applicable?(layer)
|
||||
return layer.type != DOT11TYPE_CONTROL
|
||||
end
|
||||
end
|
||||
|
||||
# Grep out our field list here
|
||||
self.constants.grep(/^([a-zA-Z0-9]+)Field$/).each do |f|
|
||||
@ -685,7 +906,6 @@ Scapy (1.2.0.1) fields that Scruby is missing:
|
||||
==============================================
|
||||
ARPSourceMACField
|
||||
BCDFloatField
|
||||
BitEnumField
|
||||
BitFieldLenField
|
||||
CharEnumField
|
||||
DHCPOptionsField
|
||||
@ -694,21 +914,13 @@ Scapy (1.2.0.1) fields that Scruby is missing:
|
||||
DNSRRField
|
||||
DNSStrField
|
||||
DestMACField
|
||||
Dot11Addr2MACField
|
||||
Dot11Addr3MACField
|
||||
Dot11Addr4MACField
|
||||
Dot11AddrMACField
|
||||
Dot11SCField
|
||||
FieldLenField
|
||||
FieldListField
|
||||
FlagsField
|
||||
IPoptionsField
|
||||
ISAKMPTransformSetField
|
||||
LEFieldLenField
|
||||
LELongField
|
||||
LESignedIntField
|
||||
LenField
|
||||
LongField
|
||||
NetBIOSNameField
|
||||
PacketField
|
||||
PacketLenField
|
||||
@ -720,7 +932,6 @@ Scapy (1.2.0.1) fields that Scruby is missing:
|
||||
SignedIntField
|
||||
SourceIPField
|
||||
SourceMACField
|
||||
StrLenField
|
||||
StrNullField
|
||||
StrStopField
|
||||
TCPOptionsField
|
||||
|
@ -17,9 +17,9 @@ def help(command = nil)
|
||||
|
||||
if command.nil?
|
||||
print <<EOF
|
||||
This is Scruby, a portable, customizable packet creation and sending/sniffing tool written in Ruby. It was tested on NetBSD and GNU/Linux, and should theoretically work on some other platforms such as FreeBSD, OpenBSD, Mac OS X and proprietary Unixes.
|
||||
This is Scruby, a portable, customizable packet creation and sending/sniffing tool written in Ruby. It was tested on NetBSD, GNU/Linux and MacOS X, and should theoretically work on some other platforms such as FreeBSD, OpenBSD and proprietary Unixes.
|
||||
|
||||
See http://sylvainsarmejeanne.free.fr/projects/scruby for more information.
|
||||
See http://sylv1.tuxfamily.org/projects/scruby.html for more information.
|
||||
|
||||
With Scruby, you can:
|
||||
- create custom packet: p=IP(:src=>"1.2.3.4", :dst=>"www.google.com")/TCP()/"GET / HTTP 1.0\\r\\n\\r\\n"
|
||||
@ -29,10 +29,10 @@ With Scruby, you can:
|
||||
- dissect a string to a recreate the packet: s=p.to_net;puts "string=\#{s.inspect}\\nresult=\#{IP(s)}"
|
||||
|
||||
Available dissectors (type "ls 'MyDissector'" to have detailed information):
|
||||
#{DISSECTORS_LIST_S.inspect}
|
||||
#{Scruby.dissectors.keys.sort.join(", ")}
|
||||
|
||||
Available functions (type "lsc 'myfunction'" to have detailed information):
|
||||
#{FUNCTIONS_LIST.inspect}
|
||||
#{(Scruby.methods - Object.methods).sort.join(", ")}
|
||||
EOF
|
||||
else
|
||||
# Executing the specific help function
|
||||
|
@ -67,7 +67,7 @@ class Layer
|
||||
# e.g. for ['type', ETHERTYPE_IPv4, IP], if the field "type"
|
||||
# in the current Ethernet layer is 0x800, then the upper layer
|
||||
# is (may be) IP.
|
||||
if self.instance_variable_get("@#{triplet[0]}") == triplet[1]
|
||||
if triplet[0] == BIND_ALWAYS or self.instance_variable_get("@#{triplet[0]}") == triplet[1]
|
||||
# Adding this possibility
|
||||
@guesses.push(triplet[2])
|
||||
break
|
||||
@ -104,6 +104,11 @@ class Layer
|
||||
return Packet./(self, upper)
|
||||
end
|
||||
|
||||
# To use 'MyField(foo, bar)' in dissectors, instead of Scruby.MyField(foo, bar)'
|
||||
def method_missing(method, *args)
|
||||
return Scruby.field(method, *args)
|
||||
end
|
||||
|
||||
# Converts an object to a string
|
||||
def to_s
|
||||
|
||||
@ -144,8 +149,10 @@ class Layer
|
||||
out = ''
|
||||
|
||||
@fields_desc.each do |field|
|
||||
if field.is_applicable?(self)
|
||||
out += field.to_net(self.instance_variable_get("@#{field.name}"))
|
||||
end
|
||||
end
|
||||
|
||||
return out
|
||||
end
|
||||
@ -159,8 +166,10 @@ class Layer
|
||||
def dissect(string)
|
||||
|
||||
@fields_desc.each do |field|
|
||||
if field.is_applicable?(self)
|
||||
string = field.dissect(self, string)
|
||||
return "" if string.nil?
|
||||
end
|
||||
return '' if string.nil?
|
||||
end
|
||||
|
||||
return string
|
||||
|
@ -16,6 +16,7 @@ def test(is, should)
|
||||
eval("module Scruby;require 'scruby';$r = #{is}.to_s == '#{should}';end;")
|
||||
if not $r
|
||||
puts "\n## test #{$test_nb} FALSE##"
|
||||
puts is.to_s
|
||||
else
|
||||
print "."
|
||||
end
|
||||
@ -30,39 +31,75 @@ $test_nb = 1
|
||||
puts "BEGIN"
|
||||
|
||||
# Constructor arguments
|
||||
test("IP(nil)", "<IP |>") #1
|
||||
test("IP(nil)", "<IP |>")
|
||||
test("IP('')", "<IP |>")
|
||||
test("IP(:foobar)", "<IP |>")
|
||||
test("IP(Hash.new)", "<IP |>")
|
||||
test("IP(Array.new)", "<IP |>")
|
||||
|
||||
# All dissectors
|
||||
test("Ether()", "<Ether |>") #6
|
||||
test("Ether()", "<Ether |>")
|
||||
test("ARP()", "<ARP |>")
|
||||
test("IP()", "<IP |>")
|
||||
test("TCP()", "<TCP |>")
|
||||
test("UDP()", "<UDP |>")
|
||||
test("ICMP()", "<ICMP |>")
|
||||
test("Raw()", "<Raw |>")
|
||||
test("TCP()", "<TCP |>")
|
||||
test("UDP()", "<UDP |>")
|
||||
test("ClassicBSDLoopback()", "<ClassicBSDLoopback |>")
|
||||
test("OpenBSDLoopback()", "<OpenBSDLoopback |>")
|
||||
test("RIFF()", "<RIFF |>")
|
||||
test("ANI()", "<ANI |>")
|
||||
test("Dot11()", "<Dot11 |>")
|
||||
test("Dot11QoS()", "<Dot11QoS |>")
|
||||
test("Dot11Beacon()", "<Dot11Beacon |>")
|
||||
test("Dot11Elt()", "<Dot11Elt |>")
|
||||
test("Dot11ATIM()", "<Dot11ATIM |>")
|
||||
test("Dot11Disas()", "<Dot11Disas |>")
|
||||
test("Dot11AssoReq()", "<Dot11AssoReq |>")
|
||||
test("Dot11AssoResp()", "<Dot11AssoResp |>")
|
||||
test("Dot11ReassoReq()", "<Dot11ReassoReq |>")
|
||||
test("Dot11ReassoResp()", "<Dot11ReassoResp |>")
|
||||
test("Dot11ProbeReq()", "<Dot11ProbeReq |>")
|
||||
test("Dot11ProbeResp()", "<Dot11ProbeResp |>")
|
||||
test("Dot11Auth()", "<Dot11Auth |>")
|
||||
test("Dot11Deauth()", "<Dot11Deauth |>")
|
||||
test("Dot11WEP()", "<Dot11WEP |>")
|
||||
test("LLC()", "<LLC |>")
|
||||
|
||||
# All dissectors with arguments
|
||||
test("Ether(:dst=>'11:11:11:11:11:11', :src=>'22:22:22:22:22:22', :type=>666)", "<Ether dst=11:11:11:11:11:11 src=22:22:22:22:22:22 type=0x29a |>") #14
|
||||
test("IP(:version=>3, :ihl=>4, :tos=>101, :len=>102, :id=>103, :flags=>2, :frag=>104, :ttl=>105, :proto=>106, :chksum=>107, :src=>'10.0.0.1', :dst=>'10.0.0.2')", "<IP version=3 ihl=4 tos=0x65 len=102 id=0x67 flags=2 frag=104 ttl=105 proto=106 chksum=0x6b src=\"10.0.0.1\" dst=\"10.0.0.2\" |>")
|
||||
test("TCP(:sport=>100, :dport=>101, :seq=>102, :ack=>103, :dataofs=>109, :reserved=>104, :flags=>105, :window=>106, :chksum=>107, :urgptr=>108)", "<TCP sport=100 dport=101 seq=102 ack=103 dataofs=109 reserved=104 flags=0x69 window=106 chksum=0x6b urgptr=108 |>")
|
||||
test("Ether(:dst=>'11:11:11:11:11:11', :src=>'22:22:22:22:22:22', :type=>666)", "<Ether dst=11:11:11:11:11:11 src=22:22:22:22:22:22 type=0x29a |>")
|
||||
test("ARP(:hwtype=>'FrameRelay', :ptype=>3, :hwlen=>1, :plen=>'IPv6', :op=>2, :hwsrc=>'11:22:33:44:55:66', :psrc=>'192.168.0.1', :hwdst=>'66:55:44:33:22:11', :pdst=>'192.168.0.2')", "<ARP hwtype=0xf ptype=0x3 hwlen=1 plen=16 op=2 hwsrc=11:22:33:44:55:66 psrc=\"192.168.0.1\" hwdst=66:55:44:33:22:11 pdst=\"192.168.0.2\" |>")
|
||||
test("IP(:version=>3, :ihl=>4, :tos=>101, :len=>102, :id=>103, :flags=>'DF', :frag=>104, :ttl=>105, :proto=>106, :chksum=>107, :src=>'10.0.0.1', :dst=>'10.0.0.2')", "<IP version=3 ihl=4 tos=0x65 len=102 id=0x67 flags=2 frag=104 ttl=105 proto=106 chksum=0x6b src=\"10.0.0.1\" dst=\"10.0.0.2\" |>")
|
||||
test("TCP(:sport=>100, :dport=>101, :seq=>102, :ack=>103, :dataofs=>109, :reserved=>104, :flags=>'SYN ACK', :window=>106, :chksum=>107, :urgptr=>108)", "<TCP sport=100 dport=101 seq=102 ack=103 dataofs=109 reserved=104 flags=18 window=106 chksum=0x6b urgptr=108 |>")
|
||||
test("UDP(:sport=>100, :dport=>101, :len=>102, :chksum=>103)", "<UDP sport=100 dport=101 len=102 chksum=0x67 |>")
|
||||
test("ICMP(:type=>100, :code=>101, :chksum=>102, :id=>103, :seq=>104)", "<ICMP type=100 code=101 chksum=0x66 id=0x67 seq=0x68 |>")
|
||||
test("Raw(:load=>'foobar')", "<Raw load=\"foobar\" |>")
|
||||
test("ClassicBSDLoopback(:header=>100)", "<ClassicBSDLoopback header=100 |>")
|
||||
test("OpenBSDLoopback(:header=>100)", "<OpenBSDLoopback header=100 |>")
|
||||
test("RIFF(:id=>'FOOB', :size=>66, :headerid=>'BARZ')", "<RIFF id=\"FOOB\" size=66 headerid=\"BARZ\" |>")
|
||||
test("ANI(:id=>'foob', :size=>12, :headersize=>21, :frames=>3, :steps=>1, :width=>2, :height=>3, :bitcount=>4, :planes=>5, :displayrate=>6, :icon=>1, :sequence=>1, :reserved=>1)", "<ANI id=\"foob\" size=12 headersize=21 frames=3 steps=1 width=2 height=3 bitcount=4 planes=5 displayrate=6 icon=1 sequence=1 reserved=1 |>")
|
||||
test("Dot11(:subtype=>1, :type=>1, :proto=>1, :FCfield=>1, :ID=>1, :addr1=>'11:11:11:11:11:11', :addr2=>'22:22:22:22:22:22', :addr3=>'33:33:33:33:33:33')", "<Dot11 subtype=1 type=1 proto=1 FCfield=1 ID=1 addr1=11:11:11:11:11:11 addr2=22:22:22:22:22:22 addr3=33:33:33:33:33:33 |>")
|
||||
test("Dot11Elt(:ID=>1, :len=>2, :info=>'ab')", "<Dot11Elt ID=1 len=2 info=\"ab\" |>")
|
||||
test("LLC(:dsap=>1, :ssap=>1, :ctrl=>1)", "<LLC dsap=0x1 ssap=0x1 ctrl=1 |>")
|
||||
|
||||
# Fields for Ether
|
||||
test("Ether().dst", "00:00:00:00:00:00") #22
|
||||
test("Ether().dst", "00:00:00:00:00:00")
|
||||
test("Ether().src", "00:00:00:00:00:00")
|
||||
test("Ether().type", "2048")
|
||||
|
||||
# Fields for ARP
|
||||
test("ARP().hwtype", "1")
|
||||
test("ARP().ptype", "2048")
|
||||
test("ARP().hwlen", "6")
|
||||
test("ARP().plen", "4")
|
||||
test("ARP().op", "1")
|
||||
test("ARP().hwsrc", "00:00:00:00:00:00")
|
||||
test("ARP().psrc", "127.0.0.1")
|
||||
test("ARP().hwdst", "00:00:00:00:00:00")
|
||||
test("ARP().pdst", "127.0.0.1")
|
||||
|
||||
# Fields for IP
|
||||
test("IP().version", "4") #25
|
||||
test("IP().version", "4")
|
||||
test("IP().ihl", "5")
|
||||
test("IP().tos", "0")
|
||||
test("IP().len", "20")
|
||||
@ -76,7 +113,7 @@ test("IP().src", "127.0.0.1")
|
||||
test("IP().dst", "127.0.0.1")
|
||||
|
||||
# Fields for TCP
|
||||
test("TCP().sport", "1024") #37
|
||||
test("TCP().sport", "1024")
|
||||
test("TCP().dport", "80")
|
||||
test("TCP().seq", "0")
|
||||
test("TCP().ack", "0")
|
||||
@ -88,20 +125,20 @@ test("TCP().chksum", "0")
|
||||
test("TCP().urgptr", "0")
|
||||
|
||||
# Fields for UDP
|
||||
test("UDP().sport", "53") #47
|
||||
test("UDP().sport", "53")
|
||||
test("UDP().dport", "53")
|
||||
test("UDP().len", "8")
|
||||
test("UDP().chksum", "0")
|
||||
|
||||
# Fields for ICMP
|
||||
test("ICMP().type", "8") #51
|
||||
test("ICMP().type", "8")
|
||||
test("ICMP().code", "0")
|
||||
test("ICMP().chksum", "0")
|
||||
test("ICMP().id", "0")
|
||||
test("ICMP().seq", "0")
|
||||
|
||||
# Fields for Raw
|
||||
test("Raw().load", "") #56
|
||||
test("Raw().load", "")
|
||||
|
||||
# Fields for ClassicBSDLoopback
|
||||
test("ClassicBSDLoopback().header", "2")
|
||||
@ -109,14 +146,56 @@ test("ClassicBSDLoopback().header", "2")
|
||||
# Fields for OpenBSDLoopback
|
||||
test("OpenBSDLoopback().header", "2")
|
||||
|
||||
# Dissecting a string
|
||||
test("Raw('foobar')", "<Raw load=\"foobar\" |>")
|
||||
# Fields for RIFF
|
||||
test("RIFF().id", "RIFF")
|
||||
test("RIFF().size", "0")
|
||||
test("RIFF().headerid", "ACON")
|
||||
|
||||
# Ether packet #60
|
||||
# Fields for ANI
|
||||
test("ANI().id", "anih")
|
||||
test("ANI().size", "36")
|
||||
test("ANI().headersize", "36")
|
||||
test("ANI().frames", "2")
|
||||
test("ANI().steps", "0")
|
||||
test("ANI().width", "0")
|
||||
test("ANI().height", "0")
|
||||
test("ANI().bitcount", "0")
|
||||
test("ANI().planes", "0")
|
||||
test("ANI().displayrate", "0")
|
||||
test("ANI().icon", "0")
|
||||
test("ANI().sequence", "0")
|
||||
test("ANI().reserved", "0")
|
||||
|
||||
# Fields for Dot11
|
||||
test("Dot11().subtype", "0")
|
||||
test("Dot11().type", "2")
|
||||
test("Dot11().proto", "0")
|
||||
test("Dot11().FCfield", "0")
|
||||
test("Dot11().ID", "0")
|
||||
test("Dot11().addr1", "00:00:00:00:00:00")
|
||||
test("Dot11().addr2", "00:00:00:00:00:00")
|
||||
test("Dot11().addr3", "00:00:00:00:00:00")
|
||||
test("Dot11().SC", "0")
|
||||
test("Dot11().addr4", "00:00:00:00:00:00")
|
||||
|
||||
# Fields for Dot11Elt
|
||||
test("Dot11Elt().ID", "0")
|
||||
test("Dot11Elt().len", "0")
|
||||
test("Dot11Elt().info", "")
|
||||
|
||||
# Fields for LLC
|
||||
test("LLC().dsap", "0")
|
||||
test("LLC().ssap", "0")
|
||||
test("LLC().ctrl", "0")
|
||||
|
||||
# Ether packet
|
||||
test("Ether(:src=>'ba:98:76:54:32:10', :type=>123).to_net.inspect", "\000\000\000\000\000\000\272\230vT2\020\000{".inspect)
|
||||
test("Ether(:dst=>'01:23:45:67:89:ab', :src=>'ba:98:76:54:32:10', :type=>123).to_net.inspect", "\001#Eg\211\253\272\230vT2\020\000{".inspect)
|
||||
|
||||
# IP packet #62
|
||||
# ARP packet
|
||||
test("(Ether(:type=>'ARP')/ARP(:hwtype=>'Ethernet', :ptype=>0x800, :hwlen=>6, :plen=>'IPv4', :op=>2, :hwsrc=>'11:22:33:44:55:66', :psrc=>'192.168.0.1', :hwdst=>'66:55:44:33:22:11', :pdst=>'192.168.0.2')).to_net.inspect", "\000\000\000\000\000\000\000\000\000\000\000\000\b\006\000\001\b\000\006\004\000\002\021\"3DUf\300\250\000\001fUD3\"\021\300\250\000\002".inspect)
|
||||
|
||||
# IP packet
|
||||
test("(IP(:version=>4, :ihl=>5, :tos=>13, :id=>103, :flags=>2, :frag=>104, :ttl=>105, :proto=>106, :src=>'1.2.3.4', :dst=>'4.3.2.1')/Raw(:load=>\"foobar\")).to_net.inspect", "E\r\000\032\000g@hij\006\225\001\002\003\004\004\003\002\001foobar".inspect)
|
||||
|
||||
# TCP packet
|
||||
@ -128,14 +207,32 @@ test("(IP(:proto=>17)/UDP(:sport=>100, :dport=>101)/Raw(:load=>\"foobar\")).to_n
|
||||
# ICMP packet
|
||||
test("(IP(:proto=>1)/ICMP(:type=>0, :code=>101, :id=>103, :seq=>104)).to_net.inspect", "E\000\000\034\000\000\000\000@\001|\337\177\000\000\001\177\000\000\001\000e\376\313\000g\000h".inspect)
|
||||
|
||||
# Dissecting Ether #66
|
||||
# RIFF packet
|
||||
test("RIFF(:id=>'FOOB', :size=>67, :headerid=>'BARZ').to_net.inspect", "FOOBC\000\000\000BARZ".inspect)
|
||||
|
||||
# ANI packet
|
||||
test("ANI(:id=>'foob', :size=>12, :headersize=>21, :frames=>3, :steps=>1, :width=>2, :height=>3, :bitcount=>4, :planes=>5, :displayrate=>6, :icon=>1, :sequence=>1, :reserved=>1).to_net.inspect", "foob\f\000\000\000\025\000\000\000\003\000\000\000\001\000\000\000\002\000\000\000\003\000\000\000\004\000\000\000\005\000\000\000\006\000\000\000\300\000\000\001".inspect)
|
||||
|
||||
# Dot11 packet
|
||||
test("Dot11(:subtype=>1, :type=>1, :proto=>1, :FCfield=>1, :ID=>1, :addr1=>'11:11:11:11:11:11', :addr2=>'22:22:22:22:22:22', :addr3=>'33:33:33:33:33:33').to_net.inspect", "\025\001\000\001\021\021\021\021\021\021".inspect)
|
||||
|
||||
# Dot11Elt packet
|
||||
test("Dot11Elt(:ID=>1, :len=>2, :info=>'ab').to_net.inspect", "\001\002ab".inspect)
|
||||
|
||||
# LLC
|
||||
test("LLC(:dsap=>1, :ssap=>1, :ctrl=>1).to_net.inspect", "\001\001\001".inspect)
|
||||
|
||||
# Dissecting Ether
|
||||
test("Ether(\"\001#Eg\211\253\272\230vT2\020\000{\")", "<Ether dst=01:23:45:67:89:ab src=ba:98:76:54:32:10 type=0x7b |>")
|
||||
|
||||
# Dissecting ARP
|
||||
test('ARP("\000\001\b\000\006\004\000\002\021\"3DUf\300\250\000\001fUD3\"\021\300\250\000\002")', "<ARP op=2 hwsrc=11:22:33:44:55:66 psrc=\"192.168.0.1\" hwdst=66:55:44:33:22:11 pdst=\"192.168.0.2\" |>")
|
||||
|
||||
# Dissecting IP
|
||||
test("IP(\"E\r\000\032\000g@hij\006\225\001\002\003\004\004\003\002\001foobar\")", "<IP tos=0xd len=26 id=0x67 flags=2 frag=104 ttl=105 proto=106 chksum=0x695 src=\"1.2.3.4\" dst=\"4.3.2.1\" |><Raw load=\"foobar\" |>")
|
||||
|
||||
# Dissecting TCP
|
||||
test("TCP(\"\000d\000e\000\000\000f\000\000\000gS\003\000j\254s\000l\")", "<TCP sport=100 dport=101 seq=102 ack=103 reserved=3 flags=0x3 window=106 chksum=0xac73 urgptr=108 |>")
|
||||
test("TCP(\"\000d\000e\000\000\000f\000\000\000gS\003\000j\254s\000l\")", "<TCP sport=100 dport=101 seq=102 ack=103 reserved=3 flags=3 window=106 chksum=0xac73 urgptr=108 |>")
|
||||
|
||||
# Dissecting UDP
|
||||
test("UDP(\"\000d\000e\000\016\311\302foobar\")", "<UDP sport=100 dport=101 len=14 chksum=0xc9c2 |><Raw load=\"foobar\" |>")
|
||||
@ -143,7 +240,28 @@ test("UDP(\"\000d\000e\000\016\311\302foobar\")", "<UDP sport=100 dport=101 len=
|
||||
# Dissecting ICMP
|
||||
test("ICMP(\"\000e\376\313\000g\000h\")", "<ICMP type=0 code=101 chksum=0xfecb id=0x67 seq=0x68 |>")
|
||||
|
||||
# Operations on layers # 71
|
||||
# Dissecting a string
|
||||
test("Raw('foobar')", "<Raw load=\"foobar\" |>")
|
||||
|
||||
# Dissecting RIFF
|
||||
test('RIFF("FOOBC\000\000\000BARZ")', "<RIFF id=\"FOOB\" size=67 headerid=\"BARZ\" |>")
|
||||
|
||||
# Dissecting ANI
|
||||
test('ANI("foob\f\000\000\000\025\000\000\000\003\000\000\000\001\000\000\000\002\000\000\000\003\000\000\000\004\000\000\000\005\000\000\000\006\000\000\000\300\000\000\001")', "<ANI id=\"foob\" size=12 headersize=21 frames=3 steps=1 width=2 height=3 bitcount=4 planes=5 displayrate=6 icon=1 sequence=1 reserved=1 |>")
|
||||
|
||||
# Dissecting Dot11
|
||||
test('Dot11("\025\001\000\001\021\021\021\021\021\021")', "<Dot11 subtype=1 type=1 proto=1 FCfield=1 ID=1 addr1=11:11:11:11:11:11 |>")
|
||||
|
||||
# Dissecting Dot11Elt
|
||||
test('Dot11Elt("\001\002ab")', "<Dot11Elt ID=1 len=2 info=\"ab\" |>")
|
||||
|
||||
# Dissecting a real Dot11 string
|
||||
test('Dot11("\x80\x00\x00\x00\xff\xff\xff\xff\xff\xff\x00\x19}\x01Y\xc4\x00\x19}\x01Y\xc4\xf0\x1e\x8bA\x9f\t)\x0c\x00\x00d\x00\x11\x04\x00\x0cLivebox-6708\x01\x08\x82\x84\x8b\x96$0Hl\x03\x01\x01\x05\x04\x00\x03\x00\x00*\x01\x00/\x01\x002\x04\x0c\x12\x18`\xdd\x16\x00P\x02\x01\x01\x00\x00P\x02\x02\x01\x00\x00P\x02\x02\x01\x00\x00P\x02\x02\xdd\x18\x00P\x02\x02")', "<Dot11 subtype=8 type=0 addr1=ff:ff:ff:ff:ff:ff addr2=00:19:7d:01:59:c4 addr3=00:19:7d:01:59:c4 SC=7920 |><Dot11Beacon timestamp=13370394624395 cap=4356 |><Dot11Elt len=12 info=\"Livebox-6708\" |><Dot11Elt ID=1 len=8 info=\"\\202\\204\\213\\226$0Hl\" |><Dot11Elt ID=3 len=1 info=\"\\001\" |><Dot11Elt ID=5 len=4 info=\"\\000\\003\\000\\000\" |><Dot11Elt ID=42 len=1 info=\"\\000\" |><Dot11Elt ID=47 len=1 info=\"\\000\" |><Dot11Elt ID=50 len=4 info=\"\\f\\022\\030`\" |><Dot11Elt ID=221 len=22 info=\"\\000P\\002\\001\\001\\000\\000P\\002\\002\\001\\000\\000P\\002\\002\\001\\000\\000P\\002\\002\" |><Dot11Elt ID=221 len=24 info=\"\\000P\\002\\002\" |>")
|
||||
|
||||
# Dissecting LLC
|
||||
test('LLC("\001\001\001")', "<LLC dsap=0x1 ssap=0x1 ctrl=1 |>")
|
||||
|
||||
# Operations on layers
|
||||
$p=Ether()/"E\000\000.\000\000\000\000@\006|\310\177\000\000\001\177\000\000\001\004\000\000P\000\000\000\000\000\000\000\000P\002 \000VF\000\000foobar"
|
||||
$p.decode_payload_as(IP)
|
||||
|
||||
@ -154,11 +272,11 @@ test("$p.last_layer", "<Raw load=\"foobar\" |>")
|
||||
test("$p.get_layer(TCP)", "<TCP chksum=0x5646 |><Raw load=\"foobar\" |>")
|
||||
|
||||
# Dissecting a string byte after byte
|
||||
test("IP('A')", "<IP ihl=1 |>") # 76
|
||||
test("IP('A')", "<IP ihl=1 |>")
|
||||
test("IP('A'*2)", "<IP ihl=1 tos=0x41 |>")
|
||||
test("IP('A'*3)", "<IP ihl=1 tos=0x41 |>")
|
||||
test("IP('A'*4)", "<IP ihl=1 tos=0x41 len=16705 |>")
|
||||
test("IP('A'*5)", "<IP ihl=1 tos=0x41 len=16705 |>") # 80
|
||||
test("IP('A'*5)", "<IP ihl=1 tos=0x41 len=16705 |>")
|
||||
test("IP('A'*6)", "<IP ihl=1 tos=0x41 len=16705 id=0x4141 |>")
|
||||
test("IP('A'*7)", "<IP ihl=1 tos=0x41 len=16705 id=0x4141 flags=2 |>")
|
||||
test("IP('A'*8)", "<IP ihl=1 tos=0x41 len=16705 id=0x4141 flags=2 frag=321 |>")
|
||||
@ -168,7 +286,7 @@ test("IP('A'*11)", "<IP ihl=1 tos=0x41 len=16705 id=0x4141 flags=2 frag=321 ttl=
|
||||
test("IP('A'*12)", "<IP ihl=1 tos=0x41 len=16705 id=0x4141 flags=2 frag=321 ttl=65 proto=65 chksum=0x4141 |>")
|
||||
test("IP('A'*13)", "<IP ihl=1 tos=0x41 len=16705 id=0x4141 flags=2 frag=321 ttl=65 proto=65 chksum=0x4141 |>")
|
||||
test("IP('A'*14)", "<IP ihl=1 tos=0x41 len=16705 id=0x4141 flags=2 frag=321 ttl=65 proto=65 chksum=0x4141 |>")
|
||||
test("IP('A'*15)", "<IP ihl=1 tos=0x41 len=16705 id=0x4141 flags=2 frag=321 ttl=65 proto=65 chksum=0x4141 |>") # 90
|
||||
test("IP('A'*15)", "<IP ihl=1 tos=0x41 len=16705 id=0x4141 flags=2 frag=321 ttl=65 proto=65 chksum=0x4141 |>")
|
||||
test("IP('A'*16)", "<IP ihl=1 tos=0x41 len=16705 id=0x4141 flags=2 frag=321 ttl=65 proto=65 chksum=0x4141 src=\"65.65.65.65\" |>")
|
||||
test("IP('A'*17)", "<IP ihl=1 tos=0x41 len=16705 id=0x4141 flags=2 frag=321 ttl=65 proto=65 chksum=0x4141 src=\"65.65.65.65\" |>")
|
||||
test("IP('A'*18)", "<IP ihl=1 tos=0x41 len=16705 id=0x4141 flags=2 frag=321 ttl=65 proto=65 chksum=0x4141 src=\"65.65.65.65\" |>")
|
||||
|
Loading…
Reference in New Issue
Block a user