lightpacket 0.0.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
LightPacket/Arp.py ADDED
@@ -0,0 +1,177 @@
1
+ # This Source Code Form is subject to the terms of the Mozilla Public
2
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ # file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
+
5
+ import struct
6
+ from .Decoration.Colors import RESET, CYAN, BLUE, PURPLE, BOLD
7
+ from .Logger.LightLogger import Logger, ErrorCode
8
+ from .BaseLayer import BaseLayer, Packet
9
+ from typing import Union
10
+ from .Layers.Mac import MacAddress
11
+ from .Layers.IPtoa import inet_aton, inet_ntoa
12
+ from .Consts import HWTYPES,ETHERTYPE
13
+
14
+ LLogger = Logger()
15
+
16
+ """
17
+ Arp Layer Creation (class ArpLayer)
18
+ """
19
+
20
+ class ArpLayer(BaseLayer):
21
+
22
+ def __init__(self, hwtype: int, ptype: int, maclen: int, plen: int, opcode: int, macsrc: Union[str, bytes],
23
+ ipsrc: str, macdst: Union[str, bytes], ipdst: str):
24
+ super().__init__()
25
+ self.hwtype = hwtype
26
+ self.ptype = ptype
27
+ self.maclen = maclen
28
+ self.plen = plen
29
+ self.opcode = opcode
30
+ self.macsrc = MacAddress(macsrc, d_or_s=0)
31
+ self.ipsrc = ipsrc
32
+ self.macdst = MacAddress(macdst, d_or_s=1)
33
+ self.ipdst = ipdst
34
+
35
+ def build(self) -> bytes:
36
+
37
+ arp = struct.pack(
38
+ '!HHBBH6s4s6s4s',
39
+ self.hwtype,
40
+ self.ptype,
41
+ self.maclen,
42
+ self.plen,
43
+ self.opcode,
44
+ bytes(self.macsrc),
45
+ inet_aton(self.ipsrc),
46
+ bytes(self.macdst),
47
+ inet_aton(self.ipdst),
48
+ )
49
+ if self.payload:
50
+ return arp + self.payload.build()
51
+ return arp
52
+
53
+ def __len__(self):
54
+ return 28
55
+
56
+ def __repr__(self):
57
+ return (
58
+ f"<Arp opcode={self.opcode} plen={self.plen} ptype={hex(self.ptype)} maclen={self.maclen} hwtype={self.hwtype} macsrc={self.macsrc} ipsrc={self.ipsrc} macdst={self.macdst} ipdst={self.ipdst}>")
59
+
60
+ def copy(self) -> 'ArpLayer':
61
+ new_layer = ArpLayer(
62
+ hwtype=self.hwtype,
63
+ ptype=self.ptype,
64
+ maclen=self.maclen,
65
+ plen=self.plen,
66
+ opcode=self.opcode,
67
+ macsrc=str(self.macsrc),
68
+ ipsrc=self.ipsrc,
69
+ macdst=str(self.macdst),
70
+ ipdst=self.ipdst
71
+ )
72
+ if self.payload:
73
+ new_layer.payload = self.payload.copy() if hasattr(self.payload, 'copy') else self.payload
74
+ if self._raw_payload:
75
+ new_layer._raw_payload = self._raw_payload
76
+ return new_layer
77
+
78
+ def _show_fields(self) -> list:
79
+ return [
80
+ f"hwtype={self.hwtype}",
81
+ f"ptype=0x{self.ptype:04x}",
82
+ f"maclen={self.maclen}",
83
+ f"plen={self.plen}",
84
+ f"opcode={self.opcode}",
85
+ f"macsrc={self.macsrc}",
86
+ f"ipsrc={self.ipsrc}",
87
+ f"macdst={self.macdst}",
88
+ f"ipdst={self.ipdst}"
89
+ ]
90
+
91
+ """
92
+ Arp Parser (separate from the builder)
93
+ """
94
+
95
+ class ArpParser:
96
+
97
+ @staticmethod
98
+ def load_as_arp_layer(raw_packet,Alr=0,verbose=False):
99
+ if type(raw_packet) is not list:
100
+ raw_packet = [raw_packet]
101
+ if hasattr(raw_packet[0], 'build') and type(raw_packet[0]) is not bytes:
102
+ raw_packet[0] = raw_packet[0].build()
103
+
104
+ if len(raw_packet[0]) < 28:
105
+ LLogger.error(error_code=ErrorCode.INVALID_DATA_LENGTH,message="Arp required header is 28 bytes")
106
+
107
+
108
+ ArpHeader = raw_packet[0]
109
+
110
+ hwtype, ptype, maclen, plen, opcode = struct.unpack('!HHBBH', ArpHeader[:8])
111
+ offset = 8
112
+ sender_mac = ArpHeader[offset:offset + 6]
113
+ offset += 6
114
+ sender_mac_str = ':'.join(f'{b:02x}' for b in sender_mac)
115
+ sender_ip = ArpHeader[offset:offset + 4]
116
+ offset += 4
117
+ sender_ip_str = inet_ntoa(sender_ip)
118
+ target_mac = ArpHeader[offset:offset + 6]
119
+ offset += 6
120
+ target_mac_str = ':'.join(f'{b:02x}' for b in target_mac)
121
+ target_ip = ArpHeader[offset:offset + 4]
122
+ target_ip_str = inet_ntoa(target_ip)
123
+ payload = ArpHeader[28:]
124
+ Lenght = len(ArpHeader[:28])
125
+ Total = len(payload) + Lenght
126
+ if opcode == 1:
127
+ opcode_e = "(who-has)"
128
+ elif opcode == 2:
129
+ opcode_e = "(is-at)"
130
+ elif opcode == 3:
131
+ opcode_e = "(RARP-req)"
132
+ elif opcode == 4:
133
+ opcode_e = "(RARP-rep)"
134
+ elif opcode == 5:
135
+ opcode_e = "(Dyn-RARP-req)"
136
+ elif opcode == 6:
137
+ opcode_e = "(Dyn-RARP-rep)"
138
+ elif opcode == 7:
139
+ opcode_e = "(Dyn-RARP-err)"
140
+ elif opcode == 8:
141
+ opcode_e = "(In-ARP-req)"
142
+ elif opcode == 9:
143
+ opcode_e = "(In-ARP-rep)"
144
+ else:
145
+ opcode_e = "(Unknown)"
146
+
147
+ if verbose:
148
+ print(f"\n{BOLD}ARP : {RESET}Len({PURPLE}{Lenght}{RESET}) Total Len({PURPLE}{Total}{RESET}) >")
149
+ print(f' {BLUE}HWTYPE:{CYAN} {hwtype} {HWTYPES.get(hwtype,'Unknown')}')
150
+ print(f' {BLUE}PTYPE:{CYAN} {hex(ptype)} {ETHERTYPE.get(ptype,'Unknown')}')
151
+ print(f' {BLUE}MACLEN:{CYAN} {maclen}')
152
+ print(f' {BLUE}PLEN:{CYAN} {plen}')
153
+ print(f' {BLUE}OPCODE:{CYAN} {opcode} {opcode_e}')
154
+ print(f' {BLUE}MAC SRC:{CYAN} {sender_mac_str}')
155
+ print(f' {BLUE}IP SRC:{CYAN} {sender_ip_str}')
156
+ print(f' {BLUE}MAC DST:{CYAN} {target_mac_str}')
157
+ print(f' {BLUE}IP DST:{CYAN} {target_ip_str}{RESET}')
158
+
159
+ if len(payload) > 0:
160
+ from .Raw import RawParser
161
+ RawParser.load_as_Raw_layer(payload,verbose=verbose)
162
+
163
+ Packet['ARP'] = {
164
+ 'hwtype': hwtype,
165
+ 'ptype': ptype,
166
+ 'maclen': maclen,
167
+ 'plen': plen,
168
+ 'opcode': opcode,
169
+ 'src_mac': sender_mac,
170
+ 'src_ip': sender_ip,
171
+ 'dst_mac': target_mac,
172
+ 'dst_ip': target_ip
173
+ }
174
+
175
+ return Packet
176
+
177
+
@@ -0,0 +1,87 @@
1
+ # This Source Code Form is subject to the terms of the Mozilla Public
2
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ # file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
+
5
+ from typing import Optional, Union, Any
6
+ import copy
7
+
8
+ Packet = {}
9
+
10
+ class BaseLayer:
11
+
12
+ def __init__(self):
13
+ self.payload: Optional['BaseLayer'] = None
14
+ self._raw_payload: Optional[bytes] = None
15
+
16
+ def __truediv__(self, other: Union['BaseLayer', bytes]) -> 'BaseLayer':
17
+ new_layer = self.copy()
18
+
19
+ new_layer.set_payload(other)
20
+ return new_layer
21
+
22
+ def __rtruediv__(self, other: Union['BaseLayer', bytes]) -> 'BaseLayer':
23
+ if isinstance(other, BaseLayer):
24
+ other.set_payload(self)
25
+ return other
26
+ elif isinstance(other, bytes):
27
+ from .Raw import RawLayer
28
+ raw = RawLayer(other)
29
+ raw.set_payload(self)
30
+ return raw
31
+ else:
32
+ raise TypeError(f"Cannot divide {type(other)} and {type(self)}")
33
+
34
+ def set_payload(self, payload: Union['BaseLayer', bytes]) -> None:
35
+ if isinstance(payload, BaseLayer):
36
+ if self.payload is not None:
37
+ last = self.payload
38
+ while last.payload is not None:
39
+ last = last.payload
40
+ last.set_payload(payload)
41
+ else:
42
+ self.payload = payload
43
+ elif isinstance(payload, bytes):
44
+ self.payload = None
45
+ self._raw_payload = payload
46
+ else:
47
+ raise TypeError(f"Payload must be BaseLayer or bytes, got {type(payload)}")
48
+
49
+ def get_payload_bytes(self) -> bytes:
50
+ if self.payload is not None:
51
+ return self.payload.build()
52
+ elif self._raw_payload is not None:
53
+ return self._raw_payload
54
+ else:
55
+ return b''
56
+
57
+ def build(self) -> bytes:
58
+ raise NotImplementedError("Subclasses must implement build()")
59
+
60
+ def copy(self) -> 'BaseLayer':
61
+ return copy.copy(self)
62
+
63
+ def __bytes__(self) -> bytes:
64
+ return self.build()
65
+
66
+ def __len__(self) -> int:
67
+ return len(self.build())
68
+
69
+ def __repr__(self) -> str:
70
+ return f"<{self.__class__.__name__}>"
71
+
72
+ def show(self, indent: int = 0) -> None:
73
+ from .Decoration.Colors import BOLD, BLUE, PURPLE, RESET, CYAN
74
+
75
+ pad = " " * indent
76
+ print(f"{pad}{BOLD}--- [ {PURPLE}{self.__class__.__name__}{PURPLE}{RESET}{BOLD} ] ---{RESET}")
77
+ args = self._show_fields()
78
+ for arg in args:
79
+ if arg is not None:
80
+ print(f"{pad} {arg}")
81
+
82
+ if self.payload:
83
+ print(f"{pad} {BLUE}\\{RESET}")
84
+ self.payload.show(indent + 4)
85
+
86
+ def _show_fields(self) -> str:
87
+ return str(self)