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 +177 -0
- LightPacket/BaseLayer.py +87 -0
- LightPacket/Consts.py +501 -0
- LightPacket/Detect_layer.py +51 -0
- LightPacket/Dot3.py +120 -0
- LightPacket/EthernetII.py +137 -0
- LightPacket/LLC.py +106 -0
- LightPacket/LightPacketLin.py +72 -0
- LightPacket/LightPacketWin.py +72 -0
- LightPacket/Raw.py +88 -0
- LightPacket/Snap.py +114 -0
- LightPacket/Version.py +5 -0
- LightPacket/__init__.py +19 -0
- lightpacket-0.0.1.dist-info/LICENSE +342 -0
- lightpacket-0.0.1.dist-info/METADATA +15 -0
- lightpacket-0.0.1.dist-info/RECORD +18 -0
- lightpacket-0.0.1.dist-info/WHEEL +5 -0
- lightpacket-0.0.1.dist-info/top_level.txt +1 -0
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
|
+
|
LightPacket/BaseLayer.py
ADDED
|
@@ -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)
|