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# SECUREAUTH LABS. Copyright 2018 SecureAuth Corporation. All rights reserved. 

2# 

3# This software is provided under under a slightly modified version 

4# of the Apache Software License. See the accompanying LICENSE file 

5# for more information. 

6# 

7 

8import array 

9import struct 

10 

11from impacket import ImpactPacket 

12from impacket.ICMP6 import ICMP6 

13 

14 

15class NDP(ICMP6): 

16 #ICMP message type numbers 

17 ROUTER_SOLICITATION = 133 

18 ROUTER_ADVERTISEMENT = 134 

19 NEIGHBOR_SOLICITATION = 135 

20 NEIGHBOR_ADVERTISEMENT = 136 

21 REDIRECT = 137 

22 

23############################################################################ 

24# Append NDP Option helper 

25 

26 def append_ndp_option(self, ndp_option): 

27 #As NDP inherits ICMP6, it is, in fact an ICMP6 "header" 

28 #The payload (where all NDP options should reside) is a child of the header 

29 self.child().get_bytes().extend(ndp_option.get_bytes()) 

30 

31 

32############################################################################ 

33 @classmethod 

34 def Router_Solicitation(class_object): 

35 message_data = struct.pack('>L', 0) #Reserved bytes 

36 return class_object.__build_message(NDP.ROUTER_SOLICITATION, message_data) 

37 

38 @classmethod 

39 def Router_Advertisement(class_object, current_hop_limit, 

40 managed_flag, other_flag, 

41 router_lifetime, reachable_time, retransmission_timer): 

42 flag_byte = 0x00 

43 if (managed_flag): 

44 flag_byte |= 0x80 

45 if (other_flag): 

46 flag_byte |= 0x40 

47 

48 message_data = struct.pack('>BBHLL', current_hop_limit, flag_byte, router_lifetime, reachable_time, retransmission_timer) 

49 return class_object.__build_message(NDP.ROUTER_ADVERTISEMENT, message_data) 

50 

51 @classmethod 

52 def Neighbor_Solicitation(class_object, target_address): 

53 message_data = struct.pack('>L', 0) #Reserved bytes 

54 message_data += ImpactPacket.array_tobytes(target_address.as_bytes()) 

55 return class_object.__build_message(NDP.NEIGHBOR_SOLICITATION, message_data) 

56 

57 

58 @classmethod 

59 def Neighbor_Advertisement(class_object, router_flag, solicited_flag, override_flag, target_address): 

60 flag_byte = 0x00 

61 if (router_flag): 

62 flag_byte |= 0x80 

63 if (solicited_flag): 

64 flag_byte |= 0x40 

65 if (override_flag): 

66 flag_byte |= 0x20 

67 

68 message_data = struct.pack('>BBBB', flag_byte, 0x00, 0x00, 0x00) #Flag byte and three reserved bytes 

69 message_data += ImpactPacket.array_tobytes(target_address.as_bytes()) 

70 return class_object.__build_message(NDP.NEIGHBOR_ADVERTISEMENT, message_data) 

71 

72 

73 @classmethod 

74 def Redirect(class_object, target_address, destination_address): 

75 message_data = struct.pack('>L', 0)# Reserved bytes 

76 message_data += ImpactPacket.array_tobytes(target_address.as_bytes()) 

77 message_data += ImpactPacket.array_tobytes(destination_address.as_bytes()) 

78 return class_object.__build_message(NDP.REDIRECT, message_data) 

79 

80 

81 @classmethod 

82 def __build_message(class_object, type, message_data): 

83 #Build NDP header 

84 ndp_packet = NDP() 

85 ndp_packet.set_type(type) 

86 ndp_packet.set_code(0) 

87 

88 #Pack payload 

89 ndp_payload = ImpactPacket.Data() 

90 ndp_payload.set_data(message_data) 

91 ndp_packet.contains(ndp_payload) 

92 

93 return ndp_packet 

94 

95 

96 

97 

98class NDP_Option(): 

99 #NDP Option Type numbers 

100 SOURCE_LINK_LAYER_ADDRESS = 1 

101 TARGET_LINK_LAYER_ADDRESS = 2 

102 PREFIX_INFORMATION = 3 

103 REDIRECTED_HEADER = 4 

104 MTU_OPTION = 5 

105 

106############################################################################ 

107 @classmethod 

108 #link_layer_address must have a size that is a multiple of 8 octets 

109 def Source_Link_Layer_Address(class_object, link_layer_address): 

110 return class_object.__Link_Layer_Address(NDP_Option.SOURCE_LINK_LAYER_ADDRESS, link_layer_address) 

111 

112 @classmethod 

113 #link_layer_address must have a size that is a multiple of 8 octets 

114 def Target_Link_Layer_Address(class_object, link_layer_address): 

115 return class_object.__Link_Layer_Address(NDP_Option.TARGET_LINK_LAYER_ADDRESS, link_layer_address) 

116 

117 @classmethod 

118 #link_layer_address must have a size that is a multiple of 8 octets 

119 def __Link_Layer_Address(class_object, option_type, link_layer_address): 

120 option_length = (len(link_layer_address) / 8) + 1 

121 option_data = ImpactPacket.array_tobytes(array.array("B", link_layer_address)) 

122 return class_object.__build_option(option_type, option_length, option_data) 

123 

124 @classmethod 

125 #Note: if we upgraded to Python 2.6, we could use collections.namedtuples for encapsulating the arguments 

126 #ENHANCEMENT - Prefix could be an instance of IP6_Address  

127 def Prefix_Information(class_object, prefix_length, on_link_flag, autonomous_flag, valid_lifetime, preferred_lifetime, prefix): 

128 

129 flag_byte = 0x00 

130 if (on_link_flag): 

131 flag_byte |= 0x80 

132 if (autonomous_flag): 

133 flag_byte |= 0x40 

134 

135 option_data = struct.pack('>BBLL', prefix_length, flag_byte, valid_lifetime, preferred_lifetime) 

136 option_data += struct.pack('>L', 0) #Reserved bytes 

137 option_data += ImpactPacket.array_tobytes(array.array("B", prefix)) 

138 option_length = 4 

139 return class_object.__build_option(NDP_Option.PREFIX_INFORMATION, option_length, option_data) 

140 

141 

142 @classmethod 

143 def Redirected_Header(class_object, original_packet): 

144 option_data = struct.pack('>BBBBBB', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)# Reserved bytes 

145 option_data += ImpactPacket.array_tobytes(array.array("B", original_packet)) 

146 option_length = (len(option_data) + 4) / 8 

147 return class_object.__build_option(NDP_Option.REDIRECTED_HEADER, option_length, option_data) 

148 

149 @classmethod 

150 def MTU(class_object, mtu): 

151 option_data = struct.pack('>BB', 0x00, 0x00)# Reserved bytes 

152 option_data += struct.pack('>L', mtu) 

153 option_length = 1 

154 return class_object.__build_option(NDP_Option.MTU_OPTION, option_length, option_data) 

155 

156 

157 @classmethod 

158 def __build_option(class_object, type, length, option_data): 

159 #Pack data 

160 data_bytes = struct.pack('>BB', type, length) 

161 data_bytes += option_data 

162 ndp_option = ImpactPacket.Data() 

163 ndp_option.set_data(data_bytes) 

164 

165 return ndp_option