# frozen_string_literal: true
require 'packetfu'
require 'packetfu/protos/arp'
require 'packetfu/protos/eth'
require 'packetfu/protos/hsrp'
require 'packetfu/protos/icmp'
require 'packetfu/protos/ip'
require 'packetfu/protos/ipv6'
require 'packetfu/protos/lldp'
require 'packetfu/protos/tcp'
require 'packetfu/protos/udp'
require 'socket'
module PWN
module Plugins
# This plugin is used for interacting with PCAP files to map out and visualize in an
# automated fashion what comprises a infrastructure, network, and/or application
module Packet
# Supported Method Parameters::
# pcap = PWN::Plugins::Packet.open_pcap_file(
# path: 'required - path to packet capture file'
# )
public_class_method def self.open_pcap_file(opts = {})
path = opts[:path].to_s.scrub.strip.chomp if File.exist?(opts[:path].to_s.scrub.strip.chomp)
PacketFu::PcapFile.read_packets(path)
rescue StandardError => e
raise e
end
# Supported Method Parameters::
# pkt = PWN::Plugins::Packet.construct_arp(
# ip_saddr: 'required - source ip of packet',
# ip_daddr: 'required - destination ip to send packet',
# payload: 'optional - packet payload defaults to empty string',
# ip_id: 'optional - defaults to 0xfeed',
# iface: 'optional - interface to send packet (defaults to eth0)',
# )
public_class_method def self.construct_arp(opts = {})
# Ethernet Header
eth_src = opts[:eth_src]
eth_dst = opts[:eth_dst]
if opts[:eth_proto]
eth_proto = opts[:eth_proto]
else
eth_proto = 0x0806 # ARP
end
# ARP Header
if opts[:arp_hw]
arp_hw = opts[:arp_hw].to_i
else
arp_hw = 1
end
if opts[:arp_proto]
arp_proto = opts[:arp_proto]
else
arp_proto = 0x0800 # IPv4
end
if opts[:arp_hw_len]
arp_hw_len = opts[:arp_hw_len].to_i
else
arp_hw_len = 6
end
if opts[:arp_proto_len]
arp_proto_len = opts[:arp_proto_len].to_i
else
arp_proto_len = 4
end
if opts[:arp_opcode]
arp_opcode = opts[:arp_opcode].to_i
else
arp_opcode = 1
end
arp_src_mac = opts[:arp_src_mac]
arp_ip_saddr = opts[:ip_saddr].to_s.scrub.strip.chomp
arp_dst_mac = opts[:arp_dst_mac]
arp_ip_daddr = opts[:ip_daddr].to_s.scrub.strip.chomp
# Payload
payload = opts[:payload]
pkt = PacketFu::ARPPacket.new(config: PacketFu::Utils.whoami?)
# Ethernet Header
pkt.eth_saddr = eth_src unless eth_src.nil?
pkt.eth_daddr = eth_dst unless eth_dst.nil?
pkt.eth_proto = eth_proto
# ARP Header
pkt.arp_hw = arp_hw
pkt.arp_proto = arp_proto
pkt.arp_hw_len = arp_hw_len
pkt.arp_proto_len = arp_proto_len
pkt.arp_opcode = arp_opcode
pkt.arp_saddr_mac = arp_src_mac
pkt.arp_saddr_ip = arp_ip_saddr
pkt.arp_daddr_mac = arp_dst_mac
pkt.arp_daddr_ip = arp_ip_daddr
# Payload
pkt.payload = payload if payload
pkt
rescue StandardError => e
raise e
end
# Supported Method Parameters::
# pkt = PWN::Plugins::Packet.construct_eth(
# ip_saddr: 'required - source ip of packet',
# ip_daddr: 'required - destination ip to send packet',
# payload: 'optional - packet payload defaults to empty string',
# ip_id: 'optional - defaults to 0xfeed',
# iface: 'optional - interface to send packet (defaults to eth0)',
# )
public_class_method def self.construct_eth(opts = {})
# Ethernet Header
eth_src = opts[:eth_src]
eth_dst = opts[:eth_dst]
if opts[:eth_proto]
eth_proto = opts[:eth_proto]
else
eth_proto = 0x0800 # IPv4
end
# Payload
payload = opts[:payload]
pkt = PacketFu::EthPacket.new(config: PacketFu::Utils.whoami?)
# Ethernet Header
pkt.eth_saddr = eth_src unless eth_src.nil?
pkt.eth_daddr = eth_dst unless eth_dst.nil?
pkt.eth_proto = eth_proto
# Payload
pkt.payload = payload if payload
pkt
rescue StandardError => e
raise e
end
# Supported Method Parameters::
# pkt = PWN::Plugins::Packet.construct_hsrp(
# ip_saddr: 'required - source ip of packet',
# ip_daddr: 'required - destination ip to send packet',
# payload: 'optional - packet payload defaults to empty string',
# ip_id: 'optional - defaults to 0xfeed',
# iface: 'optional - interface to send packet (defaults to eth0)',
# )
public_class_method def self.construct_hsrp(opts = {})
# Ethernet Header
eth_src = opts[:eth_src]
eth_dst = opts[:eth_dst]
if opts[:eth_proto]
eth_proto = opts[:eth_proto]
else
eth_proto = 0x0800 # IPv4
end
# IP Header
if opts[:ip_v]
ip_v = opts[:ip_v]
else
ip_v = 4
end
if opts[:ip_hl]
ip_hl = opts[:ip_hl]
else
ip_hl = 5
end
if opts[:ip_tos]
ip_tos = opts[:ip_tos]
else
ip_tos = 0
end
if opts[:ip_len]
ip_len = opts[:ip_len]
else
ip_len = 20
end
if opts[:ip_id]
ip_id = opts[:ip_id]
else
ip_id = 0xfeed
end
if opts[:ip_frag]
ip_frag = opts[:ip_frag]
else
ip_frag = 0
end
if opts[:ip_ttl]
ip_ttl = opts[:ip_ttl]
else
ip_ttl = 32
end
if opts[:ip_proto]
ip_proto = opts[:ip_proto]
else
ip_proto = 17 # UDP
end
if opts[:ip_sum]
ip_sum = opts[:ip_sum]
else
ip_sum = 0xffff
end
ip_saddr = opts[:ip_saddr]
ip_daddr = opts[:ip_daddr]
# UDP Header
udp_src_port = opts[:udp_src_port]
udp_dst_port = opts[:udp_dst_port]
if opts[:udp_len]
udp_len = opts[:udp_len]
else
udp_len = 8
end
if opts[:udp_sum]
udp_sum = opts[:udp_sum]
else
udp_sum = 0x0000
end
# HSRP Header
if opts[:hsrp_version]
hsrp_version = opts[:hsrp_version]
else
hsrp_version = 0
end
if opts[:hsrp_opcode]
hsrp_opcode = opts[:hsrp_opcode]
else
hsrp_opcode = 0
end
if opts[:hsrp_state]
hsrp_state = opts[:hsrp_state]
else
hsrp_state = 0
end
if opts[:hsrp_hellotime]
hsrp_state = opts[:hsrp_hellotime]
else
hsrp_state = 3
end
if opts[:hsrp_holdtime]
hsrp_holdtime = opts[:hsrp_holdtime]
else
hsrp_holdtime = 10
end
if opts[:hsrp_priority]
hsrp_priority = opts[:hsrp_priority]
else
hsrp_priority = 0
end
if opts[:hsrp_group]
hsrp_group = opts[:hsrp_group]
else
hsrp_group = 0
end
if opts[:hsrp_reserved]
hsrp_reserved = opts[:hsrp_reserved]
else
hsrp_reserved = 0
end
if opts[:hsrp_password]
hsrp_password = opts[:hsrp_password]
else
hsrp_password = "cicso\x00\x00\x00"
end
if opts[:hsrp_addr]
hsrp_addr = opts[:hsrp_addr]
else
hsrp_addr = '0.0.0.0'
end
# Payload
payload = opts[:payload]
pkt = PacketFu::HSRPPacket.new(config: PacketFu::Utils.whoami?)
# Ethernet Header
pkt.eth_saddr = eth_src unless eth_src.nil?
pkt.eth_daddr = eth_dst unless eth_dst.nil?
pkt.eth_proto = eth_proto
# IP Header
pkt.ip_v = ip_v
pkt.ip_hl = ip_hl
pkt.ip_tos = ip_tos
pkt.ip_len = ip_len
pkt.ip_id = ip_id
pkt.ip_frag = ip_frag
pkt.ip_ttl = ip_ttl
pkt.ip_proto = ip_proto
pkt.ip_sum = ip_sum
pkt.ip_saddr = ip_saddr
pkt.ip_daddr = ip_daddr
# UDP Header
pkt.udp_src = udp_src_port if udp_src_port
pkt.udp_dst = udp_dst_port if udp_dst_port
pkt.udp_len = udp_len
pkt.udp_sum = udp_sum
# HSRP Header
pkt.hsrp_version = hsrp_version
pkt.hsrp_opcode = hsrp_opcode
pkt.hsrp_state = hsrp_state
pkt.hsrp_hellotime = hsrp_hellotime
pkt.hsrp_holdtime = hsrp_holdtime
pkt.hsrp_priority = hsrp_priority
pkt.hsrp_group = hsrp_group
pkt.hsrp_reserved = hsrp_reserved
pkt.hsrp_password = hsrp_password
pkt.hsrp_addr = hsrp_addr
# Payload
pkt.payload = payload if payload
pkt
rescue StandardError => e
raise e
end
# Supported Method Parameters::
# pkt = PWN::Plugins::Packet.construct_icmp(
# ip_saddr: 'required - source ip of packet',
# ip_daddr: 'required - destination ip to send packet',
# payload: 'optional - packet payload defaults to "*ping*"',
# ip_id: 'optional - defaults to 0xfeed',
# iface: 'optional - interface to send packet (defaults to eth0)',
# )
public_class_method def self.construct_icmp(opts = {})
# Ethernet Header
eth_src = opts[:eth_src]
eth_dst = opts[:eth_dst]
if opts[:eth_proto]
eth_proto = opts[:eth_proto]
else
eth_proto = 0x0800 # IPv4
end
# IP Header
if opts[:ip_v]
ip_v = opts[:ip_v]
else
ip_v = 4
end
if opts[:ip_hl]
ip_hl = opts[:ip_hl]
else
ip_hl = 5
end
if opts[:ip_tos]
ip_tos = opts[:ip_tos]
else
ip_tos = 0
end
if opts[:ip_len]
ip_len = opts[:ip_len]
else
ip_len = 20
end
if opts[:ip_id]
ip_id = opts[:ip_id]
else
ip_id = 0xfeed
end
if opts[:ip_frag]
ip_frag = opts[:ip_frag]
else
ip_frag = 0
end
if opts[:ip_ttl]
ip_ttl = opts[:ip_ttl]
else
ip_ttl = 32
end
if opts[:ip_proto]
ip_proto = opts[:ip_proto]
else
ip_proto = 1 # ICMP
end
if opts[:ip_sum]
ip_sum = opts[:ip_sum]
else
ip_sum = 0xffff
end
ip_saddr = opts[:ip_saddr]
ip_daddr = opts[:ip_daddr]
# ICMP Header
if opts[:icmp_type]
icmp_type = opts[:icmp_type]
else
icmp_type = 8
end
if opts[:icmp_code]
icmp_code = opts[:icmp_code]
else
icmp_code = 0
end
if opts[:icmp_sum]
icmp_sum = opts[:icmp_sum]
else
icmp_sum = 0xffff
end
# Payload
opts[:payload] ? payload = opts[:payload] : payload = '*ping*'
pkt = PacketFu::ICMPPacket.new(config: PacketFu::Utils.whoami?)
# Ethernet Header
pkt.eth_saddr = eth_src unless eth_src.nil?
pkt.eth_daddr = eth_dst unless eth_dst.nil?
pkt.eth_proto = eth_proto
# IP Header
pkt.ip_v = ip_v
pkt.ip_hl = ip_hl
pkt.ip_tos = ip_tos
pkt.ip_len = ip_len
pkt.ip_id = ip_id
pkt.ip_frag = ip_frag
pkt.ip_ttl = ip_ttl
pkt.ip_proto = ip_proto
pkt.ip_sum = ip_sum
pkt.ip_saddr = ip_saddr
pkt.ip_daddr = ip_daddr
# ICMP Header
pkt.icmp_type = icmp_type
pkt.icmp_code = icmp_code
pkt.icmp_sum = icmp_sum
# Payload
pkt.payload = payload if payload
pkt
rescue StandardError => e
raise e
end
# Supported Method Parameters::
# pkt = PWN::Plugins::Packet.construct_icmpv6(
# ip_saddr: 'required - source ip of packet',
# ip_daddr: 'required - destination ip to send packet',
# payload: 'optional - packet payload defaults to empty string',
# ip_id: 'optional - defaults to 0xfeed',
# iface: 'optional - interface to send packet (defaults to eth0)',
# )
public_class_method def self.construct_icmpv6(opts = {})
# Ethernet Header
eth_src = opts[:eth_src]
eth_dst = opts[:eth_dst]
if opts[:eth_proto]
eth_proto = opts[:eth_proto]
else
eth_proto = 0x86dd # IPv6
end
# IPv6 Header
if opts[:ipv6_v]
ipv6_v = opts[:ipv6_v]
else
ipv6_v = 6
end
if opts[:ipv6_class]
ipv6_class = opts[:ipv6_class]
else
ipv6_class = 0
end
if opts[:ipv6_label]
ipv6_label = opts[:ipv6_label]
else
ipv6_label = 0
end
if opts[:ipv6_len]
ipv6_len = opts[:ipv6_len]
else
ipv6_len = 0
end
if opts[:ipv6_next]
ipv6_next = opts[:ipv6_next]
else
ipv6_next = 58
end
if opts[:ipv6_hop]
ipv6_hop = opts[:ipv6_hop]
else
ipv6_hop = 255
end
ipv6_saddr = opts[:ipv6_saddr]
ipv6_daddr = opts[:ipv6_daddr]
# ICMPv6 Header
if opts[:icmpv6_type]
icmpv6_type = opts[:icmpv6_type]
else
icmp_type = 8
end
if opts[:icmpv6_code]
icmpv6_code = opts[:icmpv6_code]
else
icmpv6_code = 0
end
if opts[:icmpv6_sum]
icmp_sum = opts[:icmpv6_sum]
else
icmpv6_sum = 0x0000
end
# Payload
payload = opts[:payload]
pkt = PacketFu::IPv6Packet.new(config: PacketFu::Utils.whoami?)
# Ethernet Header
pkt.eth_saddr = eth_src unless eth_src.nil?
pkt.eth_daddr = eth_dst unless eth_dst.nil?
pkt.eth_proto = eth_proto
# IPv6 Header
pkt.ipv6_v = ipv6_v
pkt.ipv6_hl = ipv6_hl
pkt.ipv6_tos = ipv6_tos
pkt.ipv6_len = ipv6_len
pkt.ipv6_id = ipv6_id
pkt.ipv6_frag = ipv6_frag
pkt.ipv6_saddr = ipv6_saddr
pkt.ipv6_daddr = ipv6_daddr
# ICMPv6 Header
pkt.icmpv6_type = icmpv6_type
pkt.icmpv6_code = icmpv6_code
pkt.icmpv6_sum = icmpv6_sum
# Payload
pkt.payload = payload if payload
pkt
rescue StandardError => e
raise e
end
# Supported Method Parameters::
# pkt = PWN::Plugins::Packet.construct_ip(
# ip_saddr: 'required - source ip of packet',
# ip_daddr: 'required - destination ip to send packet',
# payload: 'optional - packet payload defaults to empty string',
# ip_id: 'optional - defaults to 0xfeed',
# iface: 'optional - interface to send packet (defaults to eth0)',
# )
public_class_method def self.construct_ip(opts = {})
# Ethernet Header
eth_src = opts[:eth_src]
eth_dst = opts[:eth_dst]
if opts[:eth_proto]
eth_proto = opts[:eth_proto]
else
eth_proto = 0x0800 # IPv4
end
# IP Header
if opts[:ip_v]
ip_v = opts[:ip_v]
else
ip_v = 4
end
if opts[:ip_hl]
ip_hl = opts[:ip_hl]
else
ip_hl = 5
end
if opts[:ip_tos]
ip_tos = opts[:ip_tos]
else
ip_tos = 0
end
if opts[:ip_len]
ip_len = opts[:ip_len]
else
ip_len = 20
end
if opts[:ip_id]
ip_id = opts[:ip_id]
else
ip_id = 0xfeed
end
if opts[:ip_frag]
ip_frag = opts[:ip_frag]
else
ip_frag = 0
end
if opts[:ip_ttl]
ip_ttl = opts[:ip_ttl]
else
ip_ttl = 32
end
if opts[:ip_proto]
ip_proto = opts[:ip_proto]
else
ip_proto = -1
end
if opts[:ip_sum]
ip_sum = opts[:ip_sum]
else
ip_sum = 0xffff
end
ip_saddr = opts[:ip_saddr]
ip_daddr = opts[:ip_daddr]
# Payload
payload = opts[:payload]
pkt = PacketFu::IPPacket.new(config: PacketFu::Utils.whoami?)
# Ethernet Header
pkt.eth_saddr = eth_src unless eth_src.nil?
pkt.eth_daddr = eth_dst unless eth_dst.nil?
pkt.eth_proto = eth_proto
# IP Header
pkt.ip_v = ip_v
pkt.ip_hl = ip_hl
pkt.ip_tos = ip_tos
pkt.ip_len = ip_len
pkt.ip_id = ip_id
pkt.ip_frag = ip_frag
pkt.ip_ttl = ip_ttl
pkt.ip_proto = ip_proto
pkt.ip_sum = ip_sum
pkt.ip_saddr = ip_saddr
pkt.ip_daddr = ip_daddr
# Payload
pkt.payload = payload if payload
pkt
rescue StandardError => e
raise e
end
# Supported Method Parameters::
# pkt = PWN::Plugins::Packet.construct_ipv6(
# ip_saddr: 'required - source ip of packet',
# ip_daddr: 'required - destination ip to send packet',
# payload: 'optional - packet payload defaults to empty string',
# ip_id: 'optional - defaults to 0xfeed',
# iface: 'optional - interface to send packet (defaults to eth0)',
# )
public_class_method def self.construct_ipv6(opts = {})
# Ethernet Header
eth_src = opts[:eth_src]
eth_dst = opts[:eth_dst]
if opts[:eth_proto]
eth_proto = opts[:eth_proto]
else
eth_proto = 0x86dd # IPv6
end
# IPv6 Header
if opts[:ipv6_v]
ipv6_v = opts[:ipv6_v]
else
ipv6_v = 6
end
if opts[:ipv6_class]
ipv6_class = opts[:ipv6_class]
else
ipv6_class = 0
end
if opts[:ipv6_label]
ipv6_label = opts[:ipv6_label]
else
ipv6_label = 0
end
if opts[:ipv6_len]
ipv6_len = opts[:ipv6_len]
else
ipv6_len = 0
end
if opts[:ipv6_next]
ipv6_next = opts[:ipv6_next]
else
ipv6_next = 0
end
if opts[:ipv6_hop]
ipv6_hop = opts[:ipv6_hop]
else
ipv6_hop = 255
end
ipv6_saddr = opts[:ipv6_saddr]
ipv6_daddr = opts[:ipv6_daddr]
# Payload
payload = opts[:payload]
pkt = PacketFu::IPv6Packet.new(config: PacketFu::Utils.whoami?)
# Ethernet Header
pkt.eth_saddr = eth_src unless eth_src.nil?
pkt.eth_daddr = eth_dst unless eth_dst.nil?
pkt.eth_proto = eth_proto
# IPv6 Header
pkt.ipv6_v = ipv6_v
pkt.ipv6_hl = ipv6_hl
pkt.ipv6_tos = ipv6_tos
pkt.ipv6_len = ipv6_len
pkt.ipv6_id = ipv6_id
pkt.ipv6_frag = ipv6_frag
pkt.ipv6_saddr = ipv6_saddr
pkt.ipv6_daddr = ipv6_daddr
# Payload
pkt.payload = payload if payload
pkt
rescue StandardError => e
raise e
end
# Supported Method Parameters::
# pkt = PWN::Plugins::Packet.construct_tcp(
# ip_saddr: 'required - source ip of packet',
# ip_daddr: 'required - destination ip to send packet',
# payload: 'optional - packet payload defaults to empty string',
# ip_id: 'optional - defaults to 0xfeed',
# iface: 'optional - interface to send packet (defaults to eth0)',
# )
public_class_method def self.construct_tcp(opts = {})
# Ethernet Header
eth_src = opts[:eth_src]
eth_dst = opts[:eth_dst]
if opts[:eth_proto]
eth_proto = opts[:eth_proto]
else
eth_proto = 0x0800 # IPv4
end
# IP Header
if opts[:ip_v]
ip_v = opts[:ip_v]
else
ip_v = 4
end
if opts[:ip_hl]
ip_hl = opts[:ip_hl]
else
ip_hl = 5
end
if opts[:ip_tos]
ip_tos = opts[:ip_tos]
else
ip_tos = 0
end
if opts[:ip_len]
ip_len = opts[:ip_len]
else
ip_len = 20
end
if opts[:ip_id]
ip_id = opts[:ip_id]
else
ip_id = 0xfeed
end
if opts[:ip_frag]
ip_frag = opts[:ip_frag]
else
ip_frag = 0
end
if opts[:ip_ttl]
ip_ttl = opts[:ip_ttl]
else
ip_ttl = 32
end
if opts[:ip_proto]
ip_proto = opts[:ip_proto]
else
ip_proto = 6 # TCP
end
if opts[:ip_sum]
ip_sum = opts[:ip_sum]
else
ip_sum = 0xffff
end
ip_saddr = opts[:ip_saddr]
ip_daddr = opts[:ip_daddr]
# TCP Header
tcp_src_port = opts[:tcp_src_port]
tcp_dst_port = opts[:tcp_dst_port]
if opts[:tcp_seq]
tcp_seq = opts[:tcp_seq]
else
tcp_seq = 0x5fcea416
end
if opts[:tcp_ack]
tcp_ack = opts[:tcp_ack]
else
tcp_ack = 0x00000000
end
if opts[:tcp_hlen]
tcp_hlen = opts[:tcp_hlen]
else
tcp_hlen = 5
end
if opts[:tcp_reserved]
tcp_reserved = opts[:tcp_reserved]
else
tcp_reserved = 0
end
if opts[:tcp_ecn]
tcp_ecn = opts[:tcp_ecn]
else
tcp_ecn = 0
end
tcp_flags = opts[:tcp_flags]
if opts[:tcp_win]
tcp_win = opts[:tcp_win]
else
tcp_win = 16_384
end
if opts[:tcp_sum]
tcp_sum = opts[:tcp_sum]
else
tcp_sum = 0x1ab2
end
if opts[:tcp_urg]
tcp_urg = opts[:tcp_urg]
else
tcp_urg = 0
end
tcp_opts = opts[:tcp_opts]
# Payload
payload = opts[:payload]
pkt = PacketFu::TCPPacket.new(config: PacketFu::Utils.whoami?)
# Ethernet Header
pkt.eth_saddr = eth_src unless eth_src.nil?
pkt.eth_daddr = eth_dst unless eth_dst.nil?
pkt.eth_proto = eth_proto
# IP Header
pkt.ip_v = ip_v
pkt.ip_hl = ip_hl
pkt.ip_tos = ip_tos
pkt.ip_len = ip_len
pkt.ip_id = ip_id
pkt.ip_frag = ip_frag
pkt.ip_ttl = ip_ttl
pkt.ip_proto = ip_proto
pkt.ip_sum = ip_sum
pkt.ip_saddr = ip_saddr
pkt.ip_daddr = ip_daddr
# TCP Header
pkt.tcp_src = tcp_src_port if tcp_src_port
pkt.tcp_dst = tcp_dst_port if tcp_dst_port
pkt.tcp_seq = tcp_seq
pkt.tcp_ack = tcp_ack
pkt.tcp_hlen = tcp_hlen
pkt.tcp_reserved = tcp_reserved
pkt.tcp_ecn = tcp_ecn
pkt.tcp_flags = PacketFu::TcpFlags.new
pkt.tcp_win = tcp_win
pkt.tcp_sum = tcp_sum
pkt.tcp_urg = tcp_urg
pkt.tcp_opts = PacketFu::TcpOptions.new
# Payload
pkt.payload = payload if payload
pkt
rescue StandardError => e
raise e
end
# Supported Method Parameters::
# pkt = PWN::Plugins::Packet.construct_udp(
# ip_saddr: 'required - source ip of packet',
# ip_daddr: 'required - destination ip to send packet',
# payload: 'optional - packet payload defaults to empty string',
# ip_id: 'optional - defaults to 0xfeed',
# iface: 'optional - interface to send packet (defaults to eth0)',
# )
public_class_method def self.construct_udp(opts = {})
# Ethernet Header
eth_src = opts[:eth_src]
eth_dst = opts[:eth_dst]
if opts[:eth_proto]
eth_proto = opts[:eth_proto]
else
eth_proto = 0x0800 # IPv4
end
# IP Header
if opts[:ip_v]
ip_v = opts[:ip_v]
else
ip_v = 4
end
if opts[:ip_hl]
ip_hl = opts[:ip_hl]
else
ip_hl = 5
end
if opts[:ip_tos]
ip_tos = opts[:ip_tos]
else
ip_tos = 0
end
if opts[:ip_len]
ip_len = opts[:ip_len]
else
ip_len = 20
end
if opts[:ip_id]
ip_id = opts[:ip_id]
else
ip_id = 0xfeed
end
if opts[:ip_frag]
ip_frag = opts[:ip_frag]
else
ip_frag = 0
end
if opts[:ip_ttl]
ip_ttl = opts[:ip_ttl]
else
ip_ttl = 32
end
if opts[:ip_proto]
ip_proto = opts[:ip_proto]
else
ip_proto = 17 # UDP
end
if opts[:ip_sum]
ip_sum = opts[:ip_sum]
else
ip_sum = 0xffff
end
ip_saddr = opts[:ip_saddr]
ip_daddr = opts[:ip_daddr]
# UDP Header
udp_src_port = opts[:udp_src_port]
udp_dst_port = opts[:udp_dst_port]
if opts[:udp_len]
udp_len = opts[:udp_len]
else
udp_len = 8
end
if opts[:udp_sum]
udp_sum = opts[:udp_sum]
else
udp_sum = 0xffde
end
# Payload
payload = opts[:payload]
pkt = PacketFu::UDPPacket.new(config: PacketFu::Utils.whoami?)
# Ethernet Header
pkt.eth_saddr = eth_src unless eth_src.nil?
pkt.eth_daddr = eth_dst unless eth_dst.nil?
pkt.eth_proto = eth_proto
# IP Header
pkt.ip_v = ip_v
pkt.ip_hl = ip_hl
pkt.ip_tos = ip_tos
pkt.ip_len = ip_len
pkt.ip_id = ip_id
pkt.ip_frag = ip_frag
pkt.ip_ttl = ip_ttl
pkt.ip_proto = ip_proto
pkt.ip_sum = ip_sum
pkt.ip_saddr = ip_saddr
pkt.ip_daddr = ip_daddr
# UDP Header
pkt.udp_src = udp_src_port if udp_src_port
pkt.udp_dst = udp_dst_port if udp_dst_port
pkt.udp_len = udp_len
pkt.udp_sum = udp_sum
# Payload
pkt.payload = payload if payload
pkt
rescue StandardError => e
raise e
end
# Supported Method Parameters::
# PWN::Plugins::Packet.send(
# pkt: 'required - pkt returned from other #construct_<type> methods',
# iface: 'optional - interface to send packet (defaults to eth0)',
# )
public_class_method def self.send(opts = {})
pkt = opts[:pkt]
if opts[:iface]
iface = opts[:iface].to_s.scrub.strip.chomp
else
iface = 'eth0'
end
if pkt.instance_of?(PacketFu::TCPPacket)
this_ip = Socket.ip_address_list.detect(&:ipv4_private?).ip_address
# If we're not passing a RST packet, prevent kernel from sending its own
if this_ip == pkt.ip_saddr && pkt.tcp_flags.rst.zero?
# We have to prevent the kernel space from sending a RST
# because it won't have a socket open on the respective
# port number before we have a chance to do anything.
# In other words, the kernel will receive a SYN-ACK first,
# know it didn't send a SYN & send a RST as a result.
my_os = PWN::Plugins::DetectOS.type
case my_os
when :linux
system_resp = system(
'sudo',
'iptables',
'-C',
'OUTPUT',
'--protocol',
'tcp',
'--source',
pkt.ip_saddr,
'--destination',
pkt.ip_daddr,
'--destination-port',
pkt.tcp_dst.to_s,
'--tcp-flags',
'RST',
'RST',
'-j',
'DROP',
out: File::NULL,
err: File::NULL
)
unless system_resp
puts 'Preventing kernel from misbehaving when manipulating packets.'
system(
'sudo',
'iptables',
'-A',
'OUTPUT',
'--protocol',
'tcp',
'--source',
pkt.ip_saddr,
'--destination',
pkt.ip_daddr,
'--destination-port',
pkt.tcp_dst.to_s,
'--tcp-flags',
'RST',
'RST',
'-j',
'DROP'
)
end
pkt.recalc
pkt.to_w(iface)
system(
'sudo',
'iptables',
'-D',
'OUTPUT',
'--protocol',
'tcp',
'--source',
pkt.ip_saddr,
'--destination',
pkt.ip_daddr,
'--destination-port',
pkt.tcp_dst.to_s,
'--tcp-flags',
'RST',
'RST',
'-j',
'DROP'
)
# when :osx
# ipfilter = 'pfctl'
# ipfilter_rule = "block out proto tcp from #{pkt.ip_saddr} to #{pkt.ip_daddr} port #{pkt.tcp_dst} flags R"
# system(ipfilter, "pfctl_add_flag #{ipfilter_rule}")
# pkt.recalc
# pkt.to_w(iface)
# system(ipfilter, "pfctl_del_flag #{ipfilter_rule}")
else
raise "ERROR: #{self} Does not Support #{my_os}"
end
end
else
pkt.recalc
pkt.to_w(iface)
end
rescue StandardError => e
raise e
end
# Author(s):: 0day Inc. <support@0dayinc.com>
public_class_method def self.authors
"AUTHOR(S):
0day Inc. <support@0dayinc.com>
"
end
# Display Usage for this Module
public_class_method def self.help
puts "USAGE:
pcap = #{self}.open_pcap_file(
path: 'required - path to packet capture file'
)
pcap[0].public_methods
pcap.each do |p|
print \"IP ID: \#{p.ip_id_readable} \"
print \"IP Sum: \#{p.ip_sum_readable} \"
print \"SRC IP: \#{p.ip_src_readable} \"
print \"SRC MAC: (\#{p.eth_src_readable}) \"
print \"TCP SRC PORT: \#{p.tcp_sport} => \"
print \"DST IP: \#{p.ip_dst_readable} \"
print \"DST MAC: (\#{p.eth_dst_readable}) \"
print \"TCP DST PORT: \#{p.tcp_dport} \"
print \"ETH PROTO: \#{p.eth_proto_readable} \"
print \"TCP FLAGS: \#{p.tcp_flags_readable} \"
print \"TCP ACK: \#{p.tcp_ack_readable} \"
print \"TCP SEQ: \#{p.tcp_seq_readable} \"
print \"TCP SUM: \#{p.tcp_sum_readable} \"
print \"TCP OPTS: \#{p.tcp_opts_readable} \"
puts \"BODY: \#{p.hexify(p.payload)}\"
puts \"\\n\\n\\n\"
end
pkt = #{self}.construct_arp(
ip_saddr: 'required - source ip of packet',
ip_daddr: 'required - destination ip to send packet',
payload: 'optional - packet payload defaults to empty string',
ip_id: 'optional - defaults to 0xfeed',
iface: 'optional - interface to send packet (defaults to eth0)',
)
pkt = #{self}.construct_eth(
ip_saddr: 'required - source ip of packet',
ip_daddr: 'required - destination ip to send packet',
payload: 'optional - packet payload defaults to empty string',
ip_id: 'optional - defaults to 0xfeed',
iface: 'optional - interface to send packet (defaults to eth0)',
)
pkt = #{self}.construct_hsrp(
ip_saddr: 'required - source ip of packet',
ip_daddr: 'required - destination ip to send packet',
payload: 'optional - packet payload defaults to empty string',
ip_id: 'optional - defaults to 0xfeed',
iface: 'optional - interface to send packet (defaults to eth0)',
)
pkt = #{self}.construct_icmp(
ip_saddr: 'required - source ip of packet',
ip_daddr: 'required - destination ip to send packet',
payload: 'optional - packet payload defaults to \"*ping*\"',
ip_id: 'optional - defaults to 0xfeed',
iface: 'optional - interface to send packet (defaults to eth0)',
)
pkt = #{self}.construct_icmpv6(
ip_saddr: 'required - source ip of packet',
ip_daddr: 'required - destination ip to send packet',
payload: 'optional - packet payload defaults to empty string',
ip_id: 'optional - defaults to 0xfeed',
iface: 'optional - interface to send packet (defaults to eth0)',
)
pkt = #{self}.construct_ip(
ip_saddr: 'required - source ip of packet',
ip_daddr: 'required - destination ip to send packet',
payload: 'optional - packet payload defaults to empty string',
ip_id: 'optional - defaults to 0xfeed',
iface: 'optional - interface to send packet (defaults to eth0)',
)
pkt = #{self}.construct_ipv6(
ip_saddr: 'required - source ip of packet',
ip_daddr: 'required - destination ip to send packet',
payload: 'optional - packet payload defaults to empty string',
ip_id: 'optional - defaults to 0xfeed',
iface: 'optional - interface to send packet (defaults to eth0)',
)
pkt = #{self}.construct_tcp(
ip_saddr: 'required - source ip of packet',
ip_daddr: 'required - destination ip to send packet',
payload: 'optional - packet payload defaults to empty string',
ip_id: 'optional - defaults to 0xfeed',
iface: 'optional - interface to send packet (defaults to eth0)',
)
pkt = #{self}.construct_udp(
ip_saddr: 'required - source ip of packet',
ip_daddr: 'required - destination ip to send packet',
payload: 'optional - packet payload defaults to empty string',
ip_id: 'optional - defaults to 0xfeed',
iface: 'optional - interface to send packet (defaults to eth0)',
)
#{self}.send(
pkt: 'required - pkt returned from other #construct_<type> methods',
iface: 'optional - interface to send packet (defaults to eth0)',
)
#{self}.authors
"
end
end
end
end