Skip to content
Snippets Groups Projects
Commit 728177bf authored by Pierre Lalet's avatar Pierre Lalet Committed by GitHub
Browse files

Merge pull request #524 from gpotter2/patch-5

[Windows] support Npcap
parents d76d4bc0 9ca71249
No related branches found
No related tags found
No related merge requests found
# Config
$urlPath = "https://github.com/hsluoyz/WinDump/releases/download/v0.2/WinDump-for-Npcap-0.2.zip"
$checksum = "9182934bb822511236b4112ddaa006c95c86c864ecc5c2e3c355228463e43bf2"
############
############
# Download the file
wget $urlPath -UseBasicParsing -OutFile $PSScriptRoot"\npcap.zip"
Add-Type -AssemblyName System.IO.Compression.FileSystem
function Unzip
{
param([string]$zipfile, [string]$outpath)
[System.IO.Compression.ZipFile]::ExtractToDirectory($zipfile, $outpath)
}
Unzip $PSScriptRoot"\npcap.zip" $PSScriptRoot"\npcap"
Remove-Item $PSScriptRoot"\npcap.zip"
# Now let's check its checksum
$_chksum = $(CertUtil -hashfile $PSScriptRoot"\npcap\x64\WinDump.exe" SHA256)[1] -replace " ",""
if ($_chksum -ne $checksum){
echo "Checksums does NOT match !"
exit
} else {
echo "Checksums matches !"
}
# Finally, move it and remove tmp files
Move-Item -Force $PSScriptRoot"\npcap\x64\WinDump.exe" "C:\Windows\System32\windump.exe"
Remove-Item $PSScriptRoot"\npcap" -recurse
......@@ -11,11 +11,11 @@ environment:
build: off
install:
# Install the winpcap, windump and wireshark suites
- choco install -y winpcap wireshark
- ps: wget http://www.winpcap.org/windump/install/bin/windump_3_9_5/WinDump.exe -UseBasicParsing -OutFile C:\Windows\System32\windump.exe
# Install the npcap, windump and wireshark suites
- choco install -y npcap wireshark
- ps: .\.appveyor\InstallWindump.ps1
# Install Python modules
- "%PYTHON%\\python -m pip install cryptography coverage mock pyreadline keyboard"
- "%PYTHON%\\python -m pip install cryptography coverage mock pyreadline"
- set PATH="%PYTHON%\\Scripts\\;%PATH%"
test_script:
......
......@@ -361,7 +361,7 @@ Scapy is primarily being developed for Unix-like systems and works best on those
You need the following software packages in order to install Scapy on Windows:
* `Python <http://www.python.org>`_: `python-2.7.12.msi <https://www.python.org/ftp/python/2.7.12/python-2.7.12.msi>`_. After installation, add the Python installation directory and its \Scripts subdirectory to your PATH. Depending on your Python version, the defaults would be ``C:\Python27`` and ``C:\Python27\Scripts`` respectively.
* `WinPcap <http://www.winpcap.org/>`_: `WinPcap_4_1_3.exe <https://www.winpcap.org/install/bin/WinPcap_4_1_3.exe>`_. You might want to choose "[x] Automatically start the WinPcap driver at boot time", so that non-privileged users can sniff, especially under Vista and Windows 7. If you want to use the ethernet vendor database to resolve MAC addresses or use the ``wireshark()`` command, download `Wireshark <http://www.wireshark.org/>`_ which already includes WinPcap.
* `Npcap <https://nmap.org/npcap/>`_: `npcap-0.81.exe <https://nmap.org/npcap/dist/npcap-0.81.exe>`_. Default values are recommanded. Scapy will also work with Winpcap.
* `pyreadline <https://pypi.python.org/pypi/pyreadline>`_: `pyreadline-2.1.win-amd64.exe <https://pypi.python.org/packages/8b/13/bed49b87af0b4f345b4e54897b5ab6a4b848e4dd300ec4195a0016b8650c/pyreadline-2.1.win-amd64.exe>`_ (64bits) or `pyreadline-2.1.win32.exe <https://pypi.python.org/packages/bc/ca/316035ec616c08979bbed47fb25b843415cf2d118a2f95f55173334300a6/pyreadline-2.1.win32.exe>`_ (32bits)
* `Scapy <http://www.secdev.org/projects/scapy/>`_: `latest development version <https://github.com/secdev/scapy/archive/master.zip>`_ from the `Git repository <https://github.com/secdev/scapy>`_. Unzip the archive, open a command prompt in that directory and run "python setup.py install".
......@@ -473,6 +473,21 @@ Known bugs
* You may not be able to capture WLAN traffic on Windows. Reasons are explained on the Wireshark wiki and in the WinPcap FAQ. Try switching off promiscuous mode with ``conf.sniff_promisc=False``.
* Packets sometimes cannot be sent to localhost (or local IP addresses on your own host).
Winpcap/Npcap conflicts
^^^^^^^^^^^^^^^^^^^^^^^
As Winpcap is becoming old, it's recommanded to use Npcap instead. Npcap is part of the Nmap project.
1. If you get the message 'Winpcap is installed over Npcap.' it means that you have installed both winpcap and npcap versions, which isn't recommanded.
You may uninstall winpcap from your Program Files, then you will need to remove:
* C:/Windows/System32/wpcap.dll
* C:/Windows/System32/Packet.dll
To use npcap instead.
2. If you get the message 'The installed Windump version does not work with Npcap' it means that you have installed an old version of Windump.
Download the correct one on https://github.com/hsluoyz/WinDump/releases
Build the documentation offline
===============================
......
......@@ -7,7 +7,7 @@
Packet sending and receiving with libdnet and libpcap/WinPcap.
"""
import time,struct,sys
import time, struct, sys, platform
import socket
if not sys.platform.startswith("win"):
from fcntl import ioctl
......@@ -18,32 +18,44 @@ from scapy.utils import mac2str
from scapy.supersocket import SuperSocket
from scapy.error import Scapy_Exception, log_loading, warning
import scapy.arch
import scapy.consts
if conf.use_winpcapy:
#mostly code from https://github.com/phaethon/scapy translated to python2.X
try:
from scapy.arch.winpcapy import *
def winpcapy_get_if_list():
err = create_string_buffer(PCAP_ERRBUF_SIZE)
devs = POINTER(pcap_if_t)()
ret = []
if pcap_findalldevs(byref(devs), err) < 0:
return ret
try:
p = devs
while p:
ret.append(p.contents.name.decode('ascii'))
p = p.contents.next
return ret
finally:
pcap_freealldevs(devs)
from scapy.arch.winpcapy import *
def winpcapy_get_if_list():
err = create_string_buffer(PCAP_ERRBUF_SIZE)
devs = POINTER(pcap_if_t)()
ret = []
if pcap_findalldevs(byref(devs), err) < 0:
return ret
try:
p = devs
while p:
ret.append(p.contents.name.decode('ascii'))
p = p.contents.next
return ret
except:
raise
finally:
pcap_freealldevs(devs)
# Detect Pcap version
version = pcap_lib_version()
if "winpcap" in version.lower():
if os.path.exists(os.environ["WINDIR"] + "\\System32\\Npcap\\wpcap.dll"):
warning("Winpcap is installed over Npcap. Will use Winpcap (see 'Winpcap/Npcap conflicts' in scapy's docs)", True)
elif platform.release() != "XP":
warning("WinPcap is now deprecated (not maintened). Please use Npcap instead", True)
elif "npcap" in version.lower():
conf.use_npcap = True
LOOPBACK_NAME = scapy.consts.LOOPBACK_NAME = "Npcap Loopback Adapter"
except OSError as e:
def winpcapy_get_if_list():
return []
conf.use_winpcapy = False
if conf.interactive:
log_loading.warning("wpcap.dll is not installed. You won't be able to send/recieve packets. Visit the scapy's doc to install it")
def winpcapy_get_if_list():
return []
conf.use_winpcapy = False
if conf.interactive:
log_loading.warning("wpcap.dll is not installed. You won't be able to send/recieve packets. Visit the scapy's doc to install it")
# From BSD net/bpf.h
#BIOCIMMEDIATE=0x80044270
......
......@@ -6,8 +6,7 @@
"""
Customizations needed to support Microsoft Windows.
"""
import os,re,sys,socket,time, itertools
import os, re, sys, socket, time, itertools, platform
import subprocess as sp
from glob import glob
import tempfile
......@@ -24,6 +23,7 @@ conf.use_dnet = False
conf.use_winpcapy = True
WINDOWS = (os.name == 'nt')
NEW_RELEASE = False
#hot-patching socket for missing variables on Windows
import socket
......@@ -37,6 +37,18 @@ if not hasattr(socket, 'IPPROTO_ESP'):
from scapy.arch import pcapdnet
from scapy.arch.pcapdnet import *
def is_new_release():
release = platform.release()
try:
if float(release) >= 8:
return True
except ValueError:
if (release=="post2008Server"):
return True
return False
NEW_RELEASE = is_new_release()
def _exec_query_ps(cmd, fields):
"""Execute a PowerShell query"""
if not WINDOWS:
......@@ -270,9 +282,22 @@ if conf.prog.powershell == "powershell":
if conf.prog.sox == "sox":
conf.prog.sox = None
if conf.prog.tcpdump != "windump" and conf.use_npcap:
def test_windump_npcap():
"""Return wether windump version is correct or not"""
try:
p_test_windump = sp.Popen([conf.prog.tcpdump, "-help"], stdout=sp.PIPE, stderr=sp.STDOUT)
stdout, err = p_test_windump.communicate()
return "npcap" in stdout.lower()
except:
return False
windump_ok = test_windump_npcap()
if not windump_ok:
warning("The installed Windump version does not work with Npcap ! Refer to 'Winpcap/Npcap conflicts' in scapy's doc", True)
del windump_ok
class PcapNameNotFoundError(Scapy_Exception):
pass
import platform
def is_interface_valid(iface):
if "guid" in iface and iface["guid"]:
......@@ -283,13 +308,13 @@ def is_interface_valid(iface):
return False
def get_windows_if_list():
if is_new_release():
"""Returns windows interfaces"""
if NEW_RELEASE:
# This works only starting from Windows 8/2012 and up. For older Windows another solution is needed
# Careful: this is weird, but Get-NetAdaptater works like: (Name isn't the interface name)
# Name InterfaceDescription ifIndex Status MacAddress LinkSpeed
# ---- -------------------- ------- ------ ---------- ---------
# Ethernet Killer E2200 Gigabit Ethernet Contro... 13 Up D0-50-99-56-DD-F9 1 Gbps
query = exec_query(['Get-NetAdapter'],
['InterfaceDescription', 'InterfaceIndex', 'Name',
'InterfaceGuid', 'MacAddress']) # It is normal that it is in this order
......@@ -346,6 +371,8 @@ class NetworkInterface(object):
self.ip=get_ip_from_name(data['name'])
except (KeyError, AttributeError, NameError) as e:
print e
if not self.ip and self.name == LOOPBACK_NAME:
self.ip = "127.0.0.1"
try:
self.mac = data['mac']
except KeyError:
......@@ -501,7 +528,7 @@ def read_routes():
routes = []
release = platform.release()
try:
if is_new_release():
if NEW_RELEASE:
routes = read_routes_post2008()
elif release == "XP":
routes = read_routes_xp()
......@@ -513,7 +540,7 @@ def read_routes():
if not routes:
warning("No default IPv4 routes found. Your Windows release may no be supported and you have to enter your routes manually", True)
return routes
def read_routes_post2008():
routes = []
if_index = '(\d+)'
......
# Original license
#-------------------------------------------------------------------------------
# Name: winpcapy.py
#
......@@ -7,31 +8,34 @@
# Copyright: (c) Massimo Ciani 2009
#
#-------------------------------------------------------------------------------
# Modified for scapy's usage
## This file is part of Scapy
## See http://www.secdev.org/projects/scapy for more informations
## This program is published under a GPLv2 license
from ctypes import *
from ctypes.util import find_library
import sys
import sys, os
from scapy.consts import WINDOWS
WIN32=False
HAVE_REMOTE=False
if sys.platform.startswith('win'):
WIN32=True
if WINDOWS:
HAVE_REMOTE=True
if WIN32:
SOCKET = c_uint
_lib=CDLL('wpcap.dll')
npcap_folder = os.environ["WINDIR"] + "\\System32\\Npcap"
if os.path.exists(npcap_folder):
# Try to load npcap
os.environ['PATH'] = npcap_folder + ";" + os.environ['PATH']
_lib=CDLL("wpcap.dll")
else:
SOCKET = c_int
_lib_name = find_library('pcap')
_lib_name = find_library("pcap")
if not _lib_name:
raise OSError("Cannot fine libpcap.so library")
raise OSError("Cannot fine libpcap.so library")
_lib=CDLL(_lib_name)
##
## misc
......@@ -70,7 +74,7 @@ timeval._fields_ = [('tv_sec', c_long),
## sockaddr is used by pcap_addr.
## For example if sa_family==socket.AF_INET then we need cast
## with sockaddr_in
if WIN32:
if WINDOWS:
class sockaddr(Structure):
_fields_ = [("sa_family", c_ushort),
("sa_data",c_ubyte * 14)]
......@@ -501,8 +505,9 @@ pcap_dump_close = _lib.pcap_dump_close
pcap_dump_close.restype = None
pcap_dump_close.argtypes = [POINTER(pcap_dumper_t)]
if not WIN32:
if not WINDOWS:
#int pcap_get_selectable_fd(pcap_t, *p)
# Returns, on UNIX, a file descriptor number for a file descriptor on which one can do a select(), poll(). -1 is returned if no such descriptor exists.
pcap_get_selectable_fd = _lib.pcap_get_selectable_fd
pcap_get_selectable_fd.restype = c_int
pcap_get_selectable_fd.argtypes = [POINTER(pcap_t)]
......@@ -513,7 +518,7 @@ if not WIN32:
## (like remote packet capture, packet buffer size variation or high-precision packet injection).
## Howerver, at the moment they can be used only in Windows.
###########################################
if WIN32:
if WINDOWS:
HANDLE = c_void_p
##############
......
......@@ -391,6 +391,7 @@ debug_tls:When 1, print some TLS session secrets when they are computed.
use_dnet = os.getenv("SCAPY_USE_PCAPDNET", "").lower().startswith("y")
use_bpf = False
use_winpcapy = False
use_npcap = False
ipv6_enabled = socket.has_ipv6
ethertypes = ETHER_TYPES
protocols = IP_PROTOS
......
......@@ -32,13 +32,18 @@ class Route:
self.routes = read_routes()
def __repr__(self):
rt = "Network Netmask Gateway Iface Output IP\n"
rtlst = [("Network", "Netmask", "Gateway", "Iface", "Output IP")]
for net,msk,gw,iface,addr in self.routes:
rt += "%-15s %-15s %-15s %-15s %-15s\n" % (ltoa(net),
ltoa(msk),
gw,
(iface.name if not isinstance(iface, basestring) else iface),
addr)
rtlst.append((ltoa(net),
ltoa(msk),
gw,
(iface.name if not isinstance(iface, basestring) else iface),
addr))
colwidth = map(lambda x: max(map(lambda y: len(y), x)), apply(zip, rtlst))
fmt = " ".join(map(lambda x: "%%-%ds"%x, colwidth))
rt = "\n".join(map(lambda x: fmt % x, rtlst))
return rt
def make_route(self, host=None, net=None, gw=None, dev=None):
......
......@@ -362,7 +362,7 @@ def remove_empty_testsets(test_campaign):
def run_campaign(test_campaign, get_interactive_session, verb=3):
if WINDOWS:
# Add a route to 127.0.0.1
# Add a route to 127.0.0.1 and ::1
from scapy.arch.windows import route_add_loopback
route_add_loopback()
passed=failed=0
......
......@@ -82,21 +82,6 @@ import sys
import mock
import readline
from threading import Thread, Event
class sendTextAndTab(Thread):
"""Send text directly as Input"""
def __init__(self, event, text):
Thread.__init__(self)
self.stopped = event
self.send_text = text
def run(self):
import keyboard
time.sleep(1)
while not self.stopped.wait(0.5):
keyboard.write(self.send_text)
keyboard.send("tab")
keyboard.send("enter")
index = 0
@mock.patch("pyreadline.console.console.Console.size")
......@@ -114,12 +99,8 @@ def emulate_main_input(data, mock_readfunc, mock_pyr_size):
r_data = data[index]
if r_data.startswith("#AUTOCOMPLETE"):
send_text = re.match(r'#AUTOCOMPLETE{(.*)}', r_data).group(1)
stopFlag = Event()
thread = sendTextAndTab(stopFlag, send_text)
thread.start()
# This will block the program until the thread has pushed the stuff
r_data = readline.rl.readline()
stopFlag.set()
cmpl = readline.rl.get_completer()
r_data = cmpl(send_text, 0)
index +=1
print r_data
return r_data
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment