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

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

## 105 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# 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

8 import array

9 import struct

10

11 from impacket import ImpactPacket

12 from impacket.ICMP6 import ICMP6

13

14

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

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