Change IP in ICMP scapy - scapy

I have this ICMP packet and I want to change IP in ICMP field (I've also tried to understand what this inner IP header is), how do I access it?
I've tried things like pack[ICMP].fieldname but nothing works so far.
###[ IP ]###
version = 4
ihl = 5
tos = 0x0
len = 84
id = 2531
flags = DF
frag = 0
ttl = 63
proto = icmp
chksum = 0x1ab3
src = 192.168.100.2
dst = 192.168.100.1
\options \
###[ ICMP ]###
type = dest-unreach
code = fragmentation-needed
chksum = 0xfcfb
reserved = 0
length = 0
nexthopmtu= 0
unused = ''
###[ IP in ICMP ]###
version = 9
ihl = 2
tos = 0x5f
len = 59487
id = 0
flags =
frag = 0
ttl = 231
proto = esp
chksum = 0x800
src = 0.0.0.0
dst = 16.17.18.19
\options \
|###[ IP Option Router Alert ]###
| copy_flag = 0
| optclass = control
| option = router_alert
| length = 21
| alert = 5655
|###[ IP Option ]###
| copy_flag = 0
| optclass = control
| option = upstream_multicast_packet
| length = 25
| value = '\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+'

Nevermind I've found the answer: an ICMP() error incapsulates his original IP header, so it's IP/ICMP/IP
IPerror is the field that permits to change it.

Related

When tracing shared library functions with funclatency, no function names were displayed

When using the bcc tool funclatency, there are unknown function names.
It would be helpful if I could track the entry and return values of a number of functions contained in the library ibverbs (Infiniband).
I use funclatency to print a histogram of the ibverbs functions called by perftest.
https://github.com/iovisor/bcc/tree/master/tools
To send packages between two nodes, I use the perftest.
https://github.com/linux-rdma/perftest
To compile the perftest application, I used the following compiler flags:
CFLAGS = -g -Wall -D_GNU_SOURCE -O3 -ggdb3 -O2 -fno-omit-frame-pointer
System:
Distributor ID: Debian
Description: Debian GNU/Linux 11 (bullseye)
Release: 11
Codename: bullseye
I use funclatency like this:
sudo funclatency-bpfcc ibverbs:ibv_get*
funclatency output:
Tracing 13 functions for "ibverbs:ibv_get*"... Hit Ctrl-C to end.
Function = b'[unknown]' [784402]
nsecs : count distribution
0 -> 1 : 0 | |
2 -> 3 : 0 | |
4 -> 7 : 0 | |
8 -> 15 : 0 | |
16 -> 31 : 0 | |
32 -> 63 : 0 | |
64 -> 127 : 0 | |
128 -> 255 : 0 | |
256 -> 511 : 0 | |
512 -> 1023 : 0 | |
1024 -> 2047 : 468 |**************************** |
2048 -> 4095 : 512 |****************************** |
4096 -> 8191 : 664 |****************************************|
8192 -> 16383 : 332 |******************** |
16384 -> 32767 : 14 | |
32768 -> 65535 : 3 | |
65536 -> 131071 : 6 | |
131072 -> 262143 : 0 | |
262144 -> 524287 : 0 | |
524288 -> 1048575 : 0 | |
1048576 -> 2097151 : 0 | |
2097152 -> 4194303 : 0 | |
4194304 -> 8388607 : 0 | |
8388608 -> 16777215 : 1 | |
Here is the source code for the translation of a memory address into a function name:
https://github.com/iovisor/bcc/blob/master/src/python/bcc/init.py
def sym(addr, pid, show_module=False, show_offset=False, demangle=True):
"""sym(addr, pid, show_module=False, show_offset=False)
Translate a memory address into a function name for a pid, which is
returned. When show_module is True, the module name is also included.
When show_offset is True, the instruction offset as a hexadecimal
number is also included in the string.
A pid of less than zero will access the kernel symbol cache.
Example output when both show_module and show_offset are True:
"start_thread+0x202 [libpthread-2.24.so]"
Example output when both show_module and show_offset are False:
"start_thread"
"""
#addr is of type stacktrace_build_id
#so invoke the bsym address resolver
typeofaddr = str(type(addr))
if typeofaddr.find('bpf_stack_build_id') != -1:
sym = bcc_symbol()
b = bcc_stacktrace_build_id()
b.status = addr.status
b.build_id = addr.build_id
b.u.offset = addr.offset
res = lib.bcc_buildsymcache_resolve(BPF._bsymcache,
ct.byref(b),
ct.byref(sym))
if res < 0:
if sym.module and sym.offset:
name,offset,module = (None, sym.offset,
ct.cast(sym.module, ct.c_char_p).value)
else:
name, offset, module = (None, addr, None)
else:
name, offset, module = (sym.name, sym.offset,
ct.cast(sym.module, ct.c_char_p).value)
else:
name, offset, module = BPF._sym_cache(pid).resolve(addr, demangle)
offset = b"+0x%x" % offset if show_offset and name is not None else b""
name = name or b"[unknown]"
name = name + offset
module = b" [%s]" % os.path.basename(module) \
if show_module and module is not None else b""
return name + module
How can I read the function name correctly? It should not just return b'[unknown]'!

What are these mysterious fields in scapy?

import scapy.all as scapy
pkt = scapy.IP(src='127.0.0.1', dst='127.0.0.1')
pkt.show2()
result:
###[ IP ]###
version = 4
ihl = 5
tos = 0x0
len = 20
id = 1
flags =
frag = 0
ttl = 64
proto = ip
chksum = 0x7ce7
src = 127.0.0.1
dst = 127.0.0.1
\options \
What is chksum in scapy do i need care about it ?
what is ihl = 5 ?
what is len = 20 ?
i have searched on google about checksum but i don't know if it is related to the chksum of scapy i am not sure anyone can help ?

Get values from custom packet in IP option fields in scapy

I want to get the value of some fields in my scapy code for receiving packets, but I don't know how to do it exactly. When I print the value, I get the error that the layer is not defined or AttributeError: 'NoneType' object has no attribute 'proto'
class TELEMETRY(IPOption):
name = "TELEMETRY"
option = 31
fields_desc = [ _IPOption_HDR,
ByteField("length", 2),
Emph(SourceIPField("src", "dst")),
Emph(DestIPField("dst", "127.0.0.1")),
ShortEnumField("sport", 20, TCP_SERVICES),
ShortEnumField("dport", 80, TCP_SERVICES),
ByteEnumField("proto", 0, IP_PROTOS),
BitField("timeTaken", 0, 32),
BitField("egress_timestamp", 0, 48),
BitField("enqQdepth", 0, 19),
BitField("deqQdepth", 0, 19),
BitField("padding", 0, 2) ]
I can access the IP packet within the code blow but when I want to access the telemetry fields in my custom fields,
I get error AttributeError: 'NoneType' object has no attribute 'proto'
def handle_pkt(pkt):
ip_src=pkt[IP].src
ip_dst=pkt[IP].dst
ip_ver=pkt[IP].version
ip_id=pkt[IP].id
telemetry = pkt.getlayer(TELEMETRY)
print ip_src,ip_dst,ip_ver,ip_id, telemetry.proto
os.system(" echo %s %s %s %s %s| nc localhost 6666" % (ip_src,ip_dst,ip_ver,ip_id,telemetry.proto))
Here is the result of pkt.show2()
niffing on h4-eth0
got a packet
###[ Ethernet ]###
dst = 08:00:00:00:02:00
src = ff:ff:ff:ff:ff:ff
type = IPv4
###[ IP ]###
version = 4
ihl = 13
tos = 0x0
len = 172
id = 1
flags =
frag = 0
ttl = 63
proto = tcp
chksum = 0x5efb
src = 192.168.1.1
dst = 192.168.3.3
\options \
|###[ TELEMETRY ]###
| copy_flag = 0
| optclass = control
| option = 31
| length = 32
| src = 192.168.1.1
| dst = 192.168.3.3
| sport = 64314
| dport = 1234
| proto = tcp
| timeTaken = 11
| egress_timestamp= 7740314797
| enqQdepth = 0
| deqQdepth = 0
| padding = 0
###[ TCP ]###
sport = 64314
dport = 1234
seq = 0
ack = 0
dataofs = 5
reserved = 0
flags = S
window = 8192
chksum = 0x2d40
urgptr = 0
options = ''
Any idea would be appreciated. :)
getlayer
works when you want to get a sub layer.
In you case, you want to get a layer inside a list.
(IP.options is a list of layers)
the solution is then:
telemetry = pkt[IP].options[0]
now, for the option list might be empty for a variaty of reason, so you might want to:
if len(pkt[IP].options):
telemetry = pkt[IP].options[0]
else:
pass
# deal with it
Carcigenicate Also pointed out that you might have more of those options in your packet, you may want to deal with that too.

Why Scapy recalculates fragmentation size?

I am trying to fragment 120 bytes IP payload by 100 bytes. However, in output I got two packets one with 138 bytes and other with 50 bytes (Ethernet and IP header size are 14 and 20 bytes respectively). In first packet data offset starts from 0 to 103 and for second packet data offset starts from 104 to 119. Firstly I cannot understand why it works in this way. In order to understand I tried to look to source of defined fragment function in layers/inet.py line 552.
Scapy recalculates fragmentation size as follows:
def fragment(self, fragsize=1480):
"""Fragment IP datagrams"""
fragsize = (fragsize + 7) // 8 * 8 # <- RECALCULATION OF FRAGMENT SIZE
lst = []
fnb = 0
fl = self
while fl.underlayer is not None:
fnb += 1
fl = fl.underlayer
for p in fl:
s = raw(p[fnb].payload)
nb = (len(s) + fragsize - 1) // fragsize
for i in range(nb):
q = p.copy()
del(q[fnb].payload)
del(q[fnb].chksum)
del(q[fnb].len)
if i != nb - 1:
q[fnb].flags |= 1
q[fnb].frag += i * fragsize // 8
r = conf.raw_layer(load=s[i * fragsize:(i + 1) * fragsize])
r.overload_fields = p[fnb].payload.overload_fields.copy()
q.add_payload(r)
lst.append(q)
return lst
Can somebody explain why it is doing so?
N.B:
Ethernet header size 14 byte
IPv4 header size 20 byte
See https://github.com/secdev/scapy/issues/2424#issuecomment-576879663
From https://www.rfc-editor.org/rfc/rfc791#section-3.2 (page 25, top):
If an internet datagram is fragmented, its data portion must be broken on 8 octet boundaries.
To answer your question, fragment size must be a multiple of 8.
104 is a multiple of 8, not 100

How do you interpret a bit string using sharp snmp lib (hrPrinterDetectedErrorState)?

How do you interpret hrPrinterDetectedErrorState (http://cric.grenoble.cnrs.fr/Administrateurs/Outils/MIBS/?oid=1.3.6.1.2.1.25.3.5.1.2) or something like it using Sharp Snmp lib? Is there some kind of bit string type? It's kind of a bitmask, but you may only receive one byte instead of two (or I've seen four bytes).
Did it on my own in powershell.
[flags()] Enum hrPrinterDetectedErrorState
{
lowPaper = 0x8000
noPaper = 0x4000
lowToner = 0x2000
noToner = 0x1000
doorOpen = 0x0800
jammed = 0x0400
Offline = 0x0200
serviceRequested = 0x0100
inputTrayMissing = 0x0080
outputTrayMissing = 0x0040
markerSupplyMissing = 0x0020
outputNearFull = 0x0010
outputFull = 0x0008
inputTrayEmpty = 0x0004
overduePreventMaint = 0x0002
notUsed = 0x0001
}
function snmpmessage($data) {
$bytes = [byte[]][char[]]$data
# pack up to two bytes into an int left to right
$code = [int]$bytes[0]
$code = $code -shl 8
if ($bytes[1]) { $code = $code + $bytes[1] }
[hrPrinterDetectedErrorState]$code
}
PS C:\> snmpmessage -join [char[]](0x91,0x04)
inputTrayEmpty, serviceRequested, noToner, lowPaper

Resources