Scapy: Attribute Error: 'Tuple' Object has no attribute 'x' - scapy

pkt = srp(Dot11(type=0,subtype=4,addr1 = 'xx:xx:xx:xx:xx:xx', addr2 = 'xx:xx:xx:xx:xx:xx'), iface = 'wlan0')
If I type:
pkt.summary()
pkt.show()
pkt.sprintf()
pkt.decode_payload_as()
pkt.pdfdump()
pkt.command()
I get the Attribute error: 'tuple' object has no attribute 'e.g. summary'
This works if it's an IP or eth0 packet but not if its a WLAN

You have a mistake in your code. Unlike sniff(), srp() (like sr()) returns a Tuple of two elements:
a SndRcvList instance, for packets for which Scapy has received an asnwer.
a PacketList instance, for sent packets for which Scapy has not received an answer.
You could write:
>>> ans, unans = srp([your packet here], iface='wlan0')
>>> ans.summary()
[...]
>>> unans.summary()
[...]

Related

ACK packets forged issues: "This frame is a (suspected) retransmission"

I'm playing with scapy. I'm trying to forge JUST PSH/ACK and ACK packets in sequence
I coded two tools: A which sends PSH/ACK packets and then sniffs the resulting ACK, writing the sequence in a file to use it later
.....
bitack = random.randrange(1,656787969)
bitseq = random.randrange(1,4294967295)
if os.path.exists('test.txt'):
with open('test.txt','r') as f:
bitseq = int(f.read())
else:
with open('test.txt','w') as f:
f.write(str(bitseq))
.....
text = "Ok"
TSval = int(time.time())
TSecr = TSval
acker = IP(src="127.0.0.1",dst=destinazione"127.0.0.1")/TCP(sport=88,dport=8888,
flags="PA", seq=bitseq, ack=bitack, options=[('Timestamp', (TSval, TSecr))])/text
send(acker)
.....
rx = sniff(filter="host 127.0.0.1 and src port 8888", iface="lo", count=1)
seqcc = rx[0].getlayer(TCP).seq
ackcc = rx[0].getlayer(TCP).ack
with open('test.txt','w') as f:
f.write(str(ackcc))
print("SEQFINALE=", ackcc)
B: which sends ACK packets AFTER it sniffs a PSH/ACK packet from A. I know the ack packets contain text ( in this example the same of A), but this is what I want
....
rx = sniff(filter="host 127.0.0.1 and dst port 8888", iface="lo", count=1)
seqcc = rx[0].getlayer(TCP).seq
print("seq:", seqcc)
ackcc = rx[0].getlayer(TCP).ack
print("ack:", ackcc)
var = rx[0][Raw].load.decode(encoding='utf-8', errors='ignore')
acker = IP(src="127.0.0.1",dst="127.0.0.1")/TCP(sport=8888,dport=88, flags="A",
seq=ackcc, ack=seqcc + int(len(var)), options=[('Timestamp', (TSval, TSecr))])/var
send(acker)
.....
Everything works fine expect that wireshark gives some warning and I don't understand why:
"Expert Info (Note/Sequence): This frame is a (suspected) retransmission"
The first two packets are perfect:
Is there any issue in how I handle the sequence number/ ack number?
This makes me crazy
It is a retransmission. Your capture shows a frame from 8888 to 88 at seq=1 with 52 bytes of data (len=52). If you ever send another frame from 8888 to 88 at seq=1, it's a retransmission. TCP streams are in a single direction: A sends to B, B ACK's what A sent. (in this case, there should be an ACK=53 in a frame from 88 to 8888, either alone or piggybacking data.)

Why are there multiple IP addresses for a IP object?

In scapy, I see the following.
>>> a=IP(dst="www.slashdot.org/30")
>>> [p for p in a]
[<IP dst=216.105.38.12 |>,
<IP dst=216.105.38.13 |>,
<IP dst=216.105.38.14 |>,
<IP dst=216.105.38.15 |>]
But I don't see multiple targets with dig. Does anybody know why is it so? What is the "/30" in the above IP command mean?
$ dig www.slashdot.org a +noall +answer
www.slashdot.org. 384 IN A 216.105.38.15
Subnet Math
The /30 refers to CIDR notation. It is equivalent to a subnet mask of 255.255.255.252.
Essentially it's a mask to determine which bits of the IPv4 address are network bits and host bits.
/30 and 216.105.38.15 in binary are
11111111.11111111.11111111.11111100
11011000.01101001.00100110.00001111
To get the network address, you use a binary & to get 216.105.38.12. This subnet consists of all combinations of addresses where the host bits are variable. So these last two bits can be 00, 01, 10, or 11 (i.e. 0, 1, 2, 3). This translates to the .12, .13, .14, .15 we see scapy output.
Scapy classes
Per the scapy IP class (scapy.layers.inet.IP), when you input a subnet for the dest IP (scapy.layers.inet.DestIPField) with dst=, it's interpreted as a subnet (scapy.base_classes.Net), and all addresses in the subnet are returned.
So I will get the same result if I pass the subnet to the Net class.
>>> from scapy.base_classes import Net # if in Python and not Scapy
>>> a = Net("www.slashdot.net/30")
>>> [p for p in a]
['216.105.38.12', '216.105.38.13', '216.105.38.14', '216.105.38.15']

Configure STP protocol via scapy

I need to generate and STP traffic using scapy and when I visualize it via wireshark I get an output similar to the caption shown below:
when I run this code:
from scapy.all import STP
import scapy
from scapy.all import *
data='STP'
sendp(Ether(dst="01:80:c2:00:00:00")/LLC(dsap=0xaa, ssap=0xaa)/STP(bpdutype=0x00, bpduflags=0x01, portid=0x8002)/data, iface="eth1", count=200)
this is my wireshark output
I don't know how to change the organization code to 00:00:0c, because I believe it's the one who is making this problem
you forgot the layer SNAP
here are 2 exemples taht helped me debug:
exemple 1: your code.
exemple 2: added the SNAP layer
for both exemples:
from scapy.layers.inet import SNAP
from scapy.layers.l2 import Ether, LLC, STP
data = "STP"
exemple number1:
packet = (
Ether(dst="01:80:c2:00:00:00")
/ LLC(dsap=0xAA, ssap=0xAA)
/ STP(bpdutype=0x00, bpduflags=0x01, portid=0x8002)
/ data
)
packet.show2()
output:
###[ Ethernet ]###
dst = 01:80:c2:00:00:00
src = 4c:d9:8f:77:3b:33
type = 0x8870
###[ LLC ]###
dsap = 0xaa
ssap = 0xaa
ctrl = 3
###[ SNAP ]###
OUI = 0x0
code = 0x1
###[ 802.3 ]###
dst = 00:00:00:00:00:00
src = 00:00:00:00:00:00
len = 0
###[ Padding ]###
load = '\x00\x00\x00\x00\x00\x00\x80\x02\x01\x00\x14\x00\x02\x00\x0f\x00STP'
Do you see how scapy decode a layer named SNAP right after the LLC layer?
that makes the decoding all wrong after
so let's add it, so all the decoding will true:
exemple 2: add the SNAP layer
packet = (
Ether(dst="01:80:c2:00:00:00")
/ LLC(dsap=0xAA, ssap=0xAA)
/ SNAP()
/ STP(bpdutype=0x00, bpduflags=0x01, portid=0x8002)
/ data
)
packet.show2()
output:
###[ Ethernet ]###
dst = 01:80:c2:00:00:00
src = 4c:d9:8f:77:3b:33
type = 0x8870
###[ LLC ]###
dsap = 0xaa
ssap = 0xaa
ctrl = 3
###[ SNAP ]###
OUI = 0x0
code = 0x10b
###[ Spanning Tree Protocol ]###
proto = 0
version = 0
bpdutype = 0
bpduflags = 1
rootid = 0
rootmac = 00:00:00:00:00:00
pathcost = 0
bridgeid = 0
bridgemac = 00:00:00:00:00:00
portid = 32770
age = 1.0
maxage = 20.0
hellotime = 2.0
fwddelay = 15.0
###[ Raw ]###
load = 'STP'
it seems to look a lot better.
I didn't try with wireshark, but at the least scapy seems happy with it.

icmp response for ip options

How should I do it?
I have written a new IP Option field in the scapy 2.4 source code (scapy.layers.inet).
class IPOption_Ex(IPOption):
name = "IP Option Ex"
copy_flag = 1
option = 26
fields_desc = [_IPOption_HDR,
ByteField("op1", 16),
ShortField("op2", 0),
ShortField("op3", 0),
IPField("originator_ip", "0.0.0.0"),
LongField("op4", 0)]
It is just L3 level option so it does not involve TCP or UDP. Whenever the destination receives the new IP Option (say 26) I want a response ICMP packet (type 45). Say the response ICMP packet has four fields: 1.Type 2.Code 3.Checksum 4.source IP address. (scapy.layers.inet)
class ICMP(Packet):
name = "ICMP"
fields_desc = [ ByteEnumField("type",8, icmptypes),
MultiEnumField("code",0, icmpcodes, depends_on=lambda pkt:pkt.type,fmt="B"),
XShortField("chksum", None),
ConditionalField(IPField("originator_ip","0.0.0.0"), lambda pkt:pkt.type==45)]
Now what I don't understand how to write code in python/scapy to generate ICMP type-45 response packet from the destination and where to write in scapy source code?
You just need
IPOption_Ex.register_variant()
You'll then have
IP(options=[IPOption(option=26)])
working

Understanding the Scapy "Mac address to reach destination not found. Using broadcast." warning

If I generate an Ethernet frame without any upper layers payload and send it at layer two with sendp(), then I receive the "Mac address to reach destination not found. Using broadcast." warning and frame put to wire indeed uses ff:ff:ff:ff:ff:ff as a destination MAC address. Why is this so? Shouldn't the Scapy send exactly the frame I constructed?
My crafted package can be seen below:
>>> ls(x)
dst : DestMACField = '01:00:0c:cc:cc:cc' (None)
src : SourceMACField = '00:11:22:33:44:55' (None)
type : XShortEnumField = 0 (0)
>>> sendp(x, iface="eth0")
WARNING: Mac address to reach destination not found. Using broadcast.
.
Sent 1 packets.
>>>
Most people encountering this issue are incorrectly using send() (or sr(), sr1(), srloop()) instead of sendp() (or srp(), srp1(), srploop()). For the record, the "without-p" functions like send() are for sending layer 3 packets (send(IP())) while the "with-p" variants are for sending layer 2 packets (sendp(Ether() / IP())).
If you define x like I do below and use sendp() (and not send()) and you still have this issue, you should probably try with the latest version from the project's git repository (see https://github.com/secdev/scapy).
I've tried:
>>> x = Ether(src='01:00:0c:cc:cc:cc', dst='00:11:22:33:44:55')
>>> ls(x)
dst : DestMACField = '00:11:22:33:44:55' (None)
src : SourceMACField = '01:00:0c:cc:cc:cc' (None)
type : XShortEnumField = 0 (0)
>>> sendp(x, iface='eth0')
.
Sent 1 packets.
At the same time I was running tcpdump:
# tcpdump -eni eth0 ether host 00:11:22:33:44:55
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
12:33:47.774570 01:00:0c:cc:cc:cc > 00:11:22:33:44:55, 802.3, length 14: [|llc]

Resources