Hide keyboard shortcuts

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# 

9 

10import array 

11import struct 

12 

13from impacket import ImpactPacket 

14from impacket.ICMP6 import ICMP6 

15 

16 

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 

24 

25############################################################################ 

26# Append NDP Option helper 

27 

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()) 

32 

33 

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) 

39 

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 

49 

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) 

52 

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) 

58 

59 

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 

69 

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) 

73 

74 

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) 

81 

82 

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) 

89 

90 #Pack payload 

91 ndp_payload = ImpactPacket.Data() 

92 ndp_payload.set_data(message_data) 

93 ndp_packet.contains(ndp_payload) 

94 

95 return ndp_packet 

96 

97 

98 

99 

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 

107 

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) 

113 

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) 

118 

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) 

125 

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): 

130 

131 flag_byte = 0x00 

132 if (on_link_flag): 

133 flag_byte |= 0x80 

134 if (autonomous_flag): 

135 flag_byte |= 0x40 

136 

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) 

142 

143 

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) 

150 

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) 

157 

158 

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) 

166 

167 return ndp_option