-
Notifications
You must be signed in to change notification settings - Fork 6
/
Client.py
164 lines (131 loc) · 6.06 KB
/
Client.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
#!/usr/bin/python3
""" Description: This is the client's code. """
import socket
import urllib.request
from os import path, remove
from platform import system
from subprocess import check_output, run
from threading import Thread
from time import sleep
from bs4 import BeautifulSoup
from scapy.all import *
TAB_1 = '\t'
TAB_2 = '\t\t'
# Gets the running OS as a variable:
runningOS = system()
HOST = '10.100.102.67' # Server IP.
PORT = 1111 # Server's listening port.
restrictedSitesList = []
# main:
# Creats a socket object.
# Connects to server and prints the welcome message.
def main():
global clientSocket
# Client's Socket Object:
clientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print('Trying to connect to the server...')
try:
clientSocket.connect((HOST, PORT)) # Connects to the server's socket.
print(f'[INFO] You are connected to: {HOST} in port: {PORT}.')
welcomeMessage = clientSocket.recv(1024) # Receives welcome message.
print(welcomeMessage.decode())
except socket.error as error:
exit(
f'[ERROR] Connecting to the server failed:\n\033[31m{error}\033[0m')
# MITM:
# Checks for duplications in ARP table in both Linux and Windows.
# Iterates through the MAC addresses in the ARP table, adding them to a list.
# If a duplication occurs - the value of the MAC in the dictionary will rise by 1.
# For every MAC key that has a value of more than 1, it will send a warning message to the server.
# The scan happens every sleep(x seconds) - modify to your liking.
def MITM():
while True:
macList = []
macDict = {}
if runningOS == "Windows":
ARPmacs = check_output("arp -a", shell=True).decode()
for line in ARPmacs.splitlines():
if "dynamic" in line:
macList.append(line[24:41])
for MAC in macList:
if MAC in macDict:
macDict[MAC] = macDict[MAC] + 1
else:
macDict[MAC] = 1
for MAC, value in macDict.items():
if value >= 2:
clientSocket.send(
f'[WARNING] Found MAC address duplication. Possible Man in the Middle Attack!\nCheck this MAC: {MAC}\n\n'.encode())
elif runningOS == "Linux":
ARPmacs = check_output(
"arp | awk '{print $3}' | grep -v HW | grep -v eth0", shell=True).decode()
for line in ARPmacs.splitlines():
macList.append(line)
for MAC in macList:
if MAC in macDict:
macDict[MAC] = macDict[MAC] + 1
else:
macDict[MAC] = 1
for MAC, value in macDict.items():
if value >= 2:
clientSocket.send(
f'[WARNING]Found MAC address duplication. Possible Man in the Middle Attack!\nCheck this MAC: {MAC}\n\n'.encode())
sleep(15)
# restricted_Sites_List_Maker:
# Creats a list of website names that will be used as arguments for the DNS sniffer.
# The function gets the websites from the restricted_sites.html webpage running on the apache2 server.
# Only the server adming will have access to the html where the blacklist is stored.
# The update happens every sleep(x seconds) - modify to your liking.
def restricted_Sites_List_Maker():
while True:
# Restricted Websites webpage:
restrictedWebsites = f"http://{HOST}/restricted_sites.html"
HTMLrestrictedWebsites = urllib.request.urlopen(
restrictedWebsites).read()
soup = BeautifulSoup(HTMLrestrictedWebsites, features="lxml")
textRestictedWebsites = soup.body.get_text() # Gets text.
# Breaks into lines and remove leading and trailing space on each:
lines = (line.strip() for line in textRestictedWebsites.splitlines())
# Breaks multi-headlines into a line each:
chunks = (phrase.strip()
for line in lines for phrase in line.split(" "))
# Drops blank lines. Final result:
textRestictedWebsites = '\n'.join(chunk for chunk in chunks if chunk)
# Creates \ Overwrites \ the list of sites to a txt file from the html page.
if runningOS == "Windows":
if path.exists("Restricted_Sites.txt"):
remove("Restricted_Sites.txt")
with open("Restricted_Sites.txt", "w") as restrictedSitesFile:
restrictedSitesFile.write(textRestictedWebsites)
# Makes the file hidden.
run("attrib +h Restricted_Sites.txt", shell=True)
# Appends the site to the restrictedSitesList:
with open("Restricted_Sites.txt", "r") as f:
for siteLine in f.readlines():
restrictedSitesList.append(siteLine.strip())
elif runningOS == "Linux":
with open(".Restricted_Sites.txt", "w") as restrictedSitesFile:
restrictedSitesFile.write(textRestictedWebsites)
# Appends the site to the restrictedSitesList
with open(".Restricted_Sites.txt", "r") as f:
for siteLine in f.readlines():
restrictedSitesList.append(siteLine.strip())
sleep(60)
# findDNS:
# Sniffs DNS quearys of the client.
# Gets only the name of the website from the queary. Setting it to url variable.
# if the name of the site from the restrictedSitesList found in the current sniffed url variable - sends an alert to the server.
def findDNS(pkt):
if pkt.haslayer(DNS):
if "Qry" in pkt.summary(): # Only quearys.
# Gets only the name of the website from the queary:
url = pkt.summary().split('\"')[-2].replace("", "")[2:-2]
for site in restrictedSitesList:
if site in url:
clientSocket.send(
f'[ALERT] Entered a restricted website:\n{site}\n\n'.encode())
if __name__ == '__main__':
main()
Thread(target=restricted_Sites_List_Maker).start()
Thread(target=MITM).start()
Thread(target=sniff(prn=findDNS)).start()