Coverage for /root/GitHubProjects/impacket/impacket/NDP.py : 28%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# Impacket - Collection of Python classes for working with network protocols.
2#
3# SECUREAUTH LABS. Copyright (C) 2021 SecureAuth Corporation. All rights reserved.
4#
5# This software is provided under a slightly modified version
6# of the Apache Software License. See the accompanying LICENSE file
7# for more information.
8#
10import array
11import struct
13from impacket import ImpactPacket
14from impacket.ICMP6 import ICMP6
17class NDP(ICMP6):
18 #ICMP message type numbers
19 ROUTER_SOLICITATION = 133
20 ROUTER_ADVERTISEMENT = 134
21 NEIGHBOR_SOLICITATION = 135
22 NEIGHBOR_ADVERTISEMENT = 136
23 REDIRECT = 137
25############################################################################
26# Append NDP Option helper
28 def append_ndp_option(self, ndp_option):
29 #As NDP inherits ICMP6, it is, in fact an ICMP6 "header"
30 #The payload (where all NDP options should reside) is a child of the header
31 self.child().get_bytes().extend(ndp_option.get_bytes())
34############################################################################
35 @classmethod
36 def Router_Solicitation(class_object):
37 message_data = struct.pack('>L', 0) #Reserved bytes
38 return class_object.__build_message(NDP.ROUTER_SOLICITATION, message_data)
40 @classmethod
41 def Router_Advertisement(class_object, current_hop_limit,
42 managed_flag, other_flag,
43 router_lifetime, reachable_time, retransmission_timer):
44 flag_byte = 0x00
45 if (managed_flag):
46 flag_byte |= 0x80
47 if (other_flag):
48 flag_byte |= 0x40
50 message_data = struct.pack('>BBHLL', current_hop_limit, flag_byte, router_lifetime, reachable_time, retransmission_timer)
51 return class_object.__build_message(NDP.ROUTER_ADVERTISEMENT, message_data)
53 @classmethod
54 def Neighbor_Solicitation(class_object, target_address):
55 message_data = struct.pack('>L', 0) #Reserved bytes
56 message_data += ImpactPacket.array_tobytes(target_address.as_bytes())
57 return class_object.__build_message(NDP.NEIGHBOR_SOLICITATION, message_data)
60 @classmethod
61 def Neighbor_Advertisement(class_object, router_flag, solicited_flag, override_flag, target_address):
62 flag_byte = 0x00
63 if (router_flag):
64 flag_byte |= 0x80
65 if (solicited_flag):
66 flag_byte |= 0x40
67 if (override_flag):
68 flag_byte |= 0x20
70 message_data = struct.pack('>BBBB', flag_byte, 0x00, 0x00, 0x00) #Flag byte and three reserved bytes
71 message_data += ImpactPacket.array_tobytes(target_address.as_bytes())
72 return class_object.__build_message(NDP.NEIGHBOR_ADVERTISEMENT, message_data)
75 @classmethod
76 def Redirect(class_object, target_address, destination_address):
77 message_data = struct.pack('>L', 0)# Reserved bytes
78 message_data += ImpactPacket.array_tobytes(target_address.as_bytes())
79 message_data += ImpactPacket.array_tobytes(destination_address.as_bytes())
80 return class_object.__build_message(NDP.REDIRECT, message_data)
83 @classmethod
84 def __build_message(class_object, type, message_data):
85 #Build NDP header
86 ndp_packet = NDP()
87 ndp_packet.set_type(type)
88 ndp_packet.set_code(0)
90 #Pack payload
91 ndp_payload = ImpactPacket.Data()
92 ndp_payload.set_data(message_data)
93 ndp_packet.contains(ndp_payload)
95 return ndp_packet
100class NDP_Option():
101 #NDP Option Type numbers
102 SOURCE_LINK_LAYER_ADDRESS = 1
103 TARGET_LINK_LAYER_ADDRESS = 2
104 PREFIX_INFORMATION = 3
105 REDIRECTED_HEADER = 4
106 MTU_OPTION = 5
108############################################################################
109 @classmethod
110 #link_layer_address must have a size that is a multiple of 8 octets
111 def Source_Link_Layer_Address(class_object, link_layer_address):
112 return class_object.__Link_Layer_Address(NDP_Option.SOURCE_LINK_LAYER_ADDRESS, link_layer_address)
114 @classmethod
115 #link_layer_address must have a size that is a multiple of 8 octets
116 def Target_Link_Layer_Address(class_object, link_layer_address):
117 return class_object.__Link_Layer_Address(NDP_Option.TARGET_LINK_LAYER_ADDRESS, link_layer_address)
119 @classmethod
120 #link_layer_address must have a size that is a multiple of 8 octets
121 def __Link_Layer_Address(class_object, option_type, link_layer_address):
122 option_length = (len(link_layer_address) / 8) + 1
123 option_data = ImpactPacket.array_tobytes(array.array("B", link_layer_address))
124 return class_object.__build_option(option_type, option_length, option_data)
126 @classmethod
127 #Note: if we upgraded to Python 2.6, we could use collections.namedtuples for encapsulating the arguments
128 #ENHANCEMENT - Prefix could be an instance of IP6_Address
129 def Prefix_Information(class_object, prefix_length, on_link_flag, autonomous_flag, valid_lifetime, preferred_lifetime, prefix):
131 flag_byte = 0x00
132 if (on_link_flag):
133 flag_byte |= 0x80
134 if (autonomous_flag):
135 flag_byte |= 0x40
137 option_data = struct.pack('>BBLL', prefix_length, flag_byte, valid_lifetime, preferred_lifetime)
138 option_data += struct.pack('>L', 0) #Reserved bytes
139 option_data += ImpactPacket.array_tobytes(array.array("B", prefix))
140 option_length = 4
141 return class_object.__build_option(NDP_Option.PREFIX_INFORMATION, option_length, option_data)
144 @classmethod
145 def Redirected_Header(class_object, original_packet):
146 option_data = struct.pack('>BBBBBB', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)# Reserved bytes
147 option_data += ImpactPacket.array_tobytes(array.array("B", original_packet))
148 option_length = (len(option_data) + 4) / 8
149 return class_object.__build_option(NDP_Option.REDIRECTED_HEADER, option_length, option_data)
151 @classmethod
152 def MTU(class_object, mtu):
153 option_data = struct.pack('>BB', 0x00, 0x00)# Reserved bytes
154 option_data += struct.pack('>L', mtu)
155 option_length = 1
156 return class_object.__build_option(NDP_Option.MTU_OPTION, option_length, option_data)
159 @classmethod
160 def __build_option(class_object, type, length, option_data):
161 #Pack data
162 data_bytes = struct.pack('>BB', type, length)
163 data_bytes += option_data
164 ndp_option = ImpactPacket.Data()
165 ndp_option.set_data(data_bytes)
167 return ndp_option