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

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

## 92 statements

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

10 import array

11 import struct

12

13 from impacket import ImpactPacket

14 from impacket.ICMP6 import ICMP6

15

16

17 class 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

100 class 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