Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
S
scapy
Manage
Activity
Members
Plan
Wiki
Code
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Deploy
Releases
Package registry
Container registry
Model registry
Operate
Terraform modules
Analyze
Contributor analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
CodeLinaro
public-release-test-restored
platform
external
scapy
Commits
0dfb5bfb
Commit
0dfb5bfb
authored
9 years ago
by
n1nj4sec
Committed by
Pierre LALET
9 years ago
Browse files
Options
Downloads
Patches
Plain Diff
Windows: use Winpcap, drop DNET dependency
parent
6ac34c68
No related branches found
No related tags found
No related merge requests found
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
scapy/arch/pcapdnet.py
+298
-0
298 additions, 0 deletions
scapy/arch/pcapdnet.py
scapy/arch/windows/__init__.py
+236
-185
236 additions, 185 deletions
scapy/arch/windows/__init__.py
scapy/config.py
+1
-0
1 addition, 0 deletions
scapy/config.py
with
535 additions
and
185 deletions
scapy/arch/pcapdnet.py
100644 → 100755
+
298
−
0
View file @
0dfb5bfb
...
@@ -16,8 +16,306 @@ from scapy.utils import warning
...
@@ -16,8 +16,306 @@ from scapy.utils import warning
from
scapy.supersocket
import
SuperSocket
from
scapy.supersocket
import
SuperSocket
from
scapy.error
import
Scapy_Exception
from
scapy.error
import
Scapy_Exception
import
scapy.arch
import
scapy.arch
import
socket
if
conf
.
use_winpcapy
:
#mostly code from https://github.com/phaethon/scapy translated to python2.X
try
:
from
.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
)
except
OSError
as
e
:
if
conf
.
interactive
:
log_loading
.
error
(
"
Unable to import libpcap library: %s
"
%
e
)
conf
.
use_winpcapy
=
False
else
:
raise
# From BSD net/bpf.h
#BIOCIMMEDIATE=0x80044270
BIOCIMMEDIATE
=-
2147204496
class
PcapTimeoutElapsed
(
Scapy_Exception
):
pass
def
get_if_raw_hwaddr
(
iff
):
err
=
create_string_buffer
(
PCAP_ERRBUF_SIZE
)
devs
=
POINTER
(
pcap_if_t
)()
ret
=
"
\0\0\0\0\0\0
"
if
pcap_findalldevs
(
byref
(
devs
),
err
)
<
0
:
return
ret
try
:
p
=
devs
while
p
:
if
p
.
contents
.
name
.
endswith
(
iff
):
a
=
p
.
contents
.
addresses
while
a
:
if
hasattr
(
socket
,
'
AF_LINK
'
)
and
a
.
contents
.
addr
.
contents
.
sa_family
==
socket
.
AF_LINK
:
ap
=
a
.
contents
.
addr
val
=
cast
(
ap
,
POINTER
(
sockaddr_dl
))
ret
=
str
(
val
.
contents
.
sdl_data
[
val
.
contents
.
sdl_nlen
:
val
.
contents
.
sdl_nlen
+
val
.
contents
.
sdl_alen
])
a
=
a
.
contents
.
next
break
p
=
p
.
contents
.
next
return
ret
finally
:
pcap_freealldevs
(
devs
)
def
get_if_raw_addr
(
iff
):
err
=
create_string_buffer
(
PCAP_ERRBUF_SIZE
)
devs
=
POINTER
(
pcap_if_t
)()
ret
=
"
\0\0\0\0
"
if
pcap_findalldevs
(
byref
(
devs
),
err
)
<
0
:
return
ret
try
:
p
=
devs
while
p
:
if
p
.
contents
.
name
.
endswith
(
iff
):
a
=
p
.
contents
.
addresses
while
a
:
if
a
.
contents
.
addr
.
contents
.
sa_family
==
socket
.
AF_INET
:
ap
=
a
.
contents
.
addr
val
=
cast
(
ap
,
POINTER
(
sockaddr_in
))
#ret = bytes(val.contents.sin_addr[:4])
ret
=
""
.
join
([
chr
(
x
)
for
x
in
val
.
contents
.
sin_addr
[:
4
]])
a
=
a
.
contents
.
next
break
p
=
p
.
contents
.
next
return
ret
finally
:
pcap_freealldevs
(
devs
)
get_if_list
=
winpcapy_get_if_list
def
in6_getifaddr
():
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
ret
=
[]
while
p
:
a
=
p
.
contents
.
addresses
while
a
:
if
a
.
contents
.
addr
.
contents
.
sa_family
==
socket
.
AF_INET6
:
ap
=
a
.
contents
.
addr
val
=
cast
(
ap
,
POINTER
(
sockaddr_in6
))
addr
=
socket
.
inet_ntop
(
socket
.
AF_INET6
,
str
(
val
.
contents
.
sin6_addr
[:]))
scope
=
scapy
.
utils6
.
in6_getscope
(
addr
)
ret
.
append
((
addr
,
scope
,
p
.
contents
.
name
.
decode
(
'
ascii
'
)))
a
=
a
.
contents
.
next
p
=
p
.
contents
.
next
return
ret
finally
:
pcap_freealldevs
(
devs
)
from
ctypes
import
POINTER
,
byref
,
create_string_buffer
class
_PcapWrapper_pypcap
:
def
__init__
(
self
,
device
,
snaplen
,
promisc
,
to_ms
):
self
.
errbuf
=
create_string_buffer
(
PCAP_ERRBUF_SIZE
)
self
.
iface
=
create_string_buffer
(
device
)
self
.
pcap
=
pcap_open_live
(
self
.
iface
,
snaplen
,
promisc
,
to_ms
,
self
.
errbuf
)
self
.
header
=
POINTER
(
pcap_pkthdr
)()
self
.
pkt_data
=
POINTER
(
c_ubyte
)()
self
.
bpf_program
=
bpf_program
()
def
next
(
self
):
c
=
pcap_next_ex
(
self
.
pcap
,
byref
(
self
.
header
),
byref
(
self
.
pkt_data
))
if
not
c
>
0
:
return
ts
=
self
.
header
.
contents
.
ts
.
tv_sec
pkt
=
""
.
join
([
chr
(
i
)
for
i
in
self
.
pkt_data
[:
self
.
header
.
contents
.
len
]
])
#pkt = bytes(self.pkt_data[:self.header.contents.len])
return
ts
,
pkt
def
datalink
(
self
):
return
pcap_datalink
(
self
.
pcap
)
def
fileno
(
self
):
if
sys
.
platform
.
startswith
(
"
win
"
):
error
(
"
Cannot get selectable PCAP fd on Windows
"
)
return
0
return
pcap_get_selectable_fd
(
self
.
pcap
)
def
setfilter
(
self
,
f
):
filter_exp
=
create_string_buffer
(
f
)
if
pcap_compile
(
self
.
pcap
,
byref
(
self
.
bpf_program
),
filter_exp
,
0
,
-
1
)
==
-
1
:
error
(
"
Could not compile filter expression %s
"
%
f
)
return
False
else
:
if
pcap_setfilter
(
self
.
pcap
,
byref
(
self
.
bpf_program
))
==
-
1
:
error
(
"
Could not install filter %s
"
%
f
)
return
False
return
True
def
setnonblock
(
self
,
i
):
pcap_setnonblock
(
self
.
pcap
,
i
,
self
.
errbuf
)
def
send
(
self
,
x
):
pcap_sendpacket
(
self
.
pcap
,
x
,
len
(
x
))
def
close
(
self
):
pcap_close
(
self
.
pcap
)
open_pcap
=
lambda
*
args
,
**
kargs
:
_PcapWrapper_pypcap
(
*
args
,
**
kargs
)
class
PcapTimeoutElapsed
(
Scapy_Exception
):
pass
class
L2pcapListenSocket
(
SuperSocket
):
desc
=
"
read packets at layer 2 using libpcap
"
def
__init__
(
self
,
iface
=
None
,
type
=
ETH_P_ALL
,
promisc
=
None
,
filter
=
None
):
self
.
type
=
type
self
.
outs
=
None
self
.
iface
=
iface
if
iface
is
None
:
iface
=
conf
.
iface
if
promisc
is
None
:
promisc
=
conf
.
sniff_promisc
self
.
promisc
=
promisc
self
.
ins
=
open_pcap
(
iface
,
1600
,
self
.
promisc
,
100
)
try
:
ioctl
(
self
.
ins
.
fileno
(),
BIOCIMMEDIATE
,
struct
.
pack
(
"
I
"
,
1
))
except
:
pass
if
type
==
ETH_P_ALL
:
# Do not apply any filter if Ethernet type is given
if
conf
.
except_filter
:
if
filter
:
filter
=
"
(%s) and not (%s)
"
%
(
filter
,
conf
.
except_filter
)
else
:
filter
=
"
not (%s)
"
%
conf
.
except_filter
if
filter
:
self
.
ins
.
setfilter
(
filter
)
def
close
(
self
):
self
.
ins
.
close
()
def
recv
(
self
,
x
=
MTU
):
ll
=
self
.
ins
.
datalink
()
if
ll
in
conf
.
l2types
:
cls
=
conf
.
l2types
[
ll
]
else
:
cls
=
conf
.
default_l2
warning
(
"
Unable to guess datalink type (interface=%s linktype=%i). Using %s
"
%
(
self
.
iface
,
ll
,
cls
.
name
))
pkt
=
None
while
pkt
is
None
:
pkt
=
self
.
ins
.
next
()
if
pkt
is
not
None
:
ts
,
pkt
=
pkt
if
scapy
.
arch
.
WINDOWS
and
pkt
is
None
:
raise
PcapTimeoutElapsed
try
:
pkt
=
cls
(
pkt
)
except
KeyboardInterrupt
:
raise
except
:
if
conf
.
debug_dissector
:
raise
pkt
=
conf
.
raw_layer
(
pkt
)
pkt
.
time
=
ts
return
pkt
def
send
(
self
,
x
):
raise
Scapy_Exception
(
"
Can
'
t send anything with L2pcapListenSocket
"
)
conf
.
L2listen
=
L2pcapListenSocket
class
L2pcapSocket
(
SuperSocket
):
desc
=
"
read/write packets at layer 2 using only libpcap
"
def
__init__
(
self
,
iface
=
None
,
type
=
ETH_P_ALL
,
filter
=
None
,
nofilter
=
0
):
if
iface
is
None
:
iface
=
conf
.
iface
self
.
iface
=
iface
self
.
ins
=
open_pcap
(
iface
,
1600
,
0
,
100
)
try
:
ioctl
(
self
.
ins
.
fileno
(),
BIOCIMMEDIATE
,
struct
.
pack
(
"
I
"
,
1
))
except
:
pass
if
nofilter
:
if
type
!=
ETH_P_ALL
:
# PF_PACKET stuff. Need to emulate this for pcap
filter
=
"
ether proto %i
"
%
type
else
:
filter
=
None
else
:
if
conf
.
except_filter
:
if
filter
:
filter
=
"
(%s) and not (%s)
"
%
(
filter
,
conf
.
except_filter
)
else
:
filter
=
"
not (%s)
"
%
conf
.
except_filter
if
type
!=
ETH_P_ALL
:
# PF_PACKET stuff. Need to emulate this for pcap
if
filter
:
filter
=
"
(ether proto %i) and (%s)
"
%
(
type
,
filter
)
else
:
filter
=
"
ether proto %i
"
%
type
if
filter
:
self
.
ins
.
setfilter
(
filter
)
def
send
(
self
,
x
):
sx
=
str
(
x
)
if
hasattr
(
x
,
"
sent_time
"
):
x
.
sent_time
=
time
.
time
()
return
self
.
ins
.
send
(
sx
)
def
recv
(
self
,
x
=
MTU
):
ll
=
self
.
ins
.
datalink
()
if
ll
in
conf
.
l2types
:
cls
=
conf
.
l2types
[
ll
]
else
:
cls
=
conf
.
default_l2
warning
(
"
Unable to guess datalink type (interface=%s linktype=%i). Using %s
"
%
(
self
.
iface
,
ll
,
cls
.
name
))
pkt
=
self
.
ins
.
next
()
if
pkt
is
not
None
:
ts
,
pkt
=
pkt
if
pkt
is
None
:
return
try
:
pkt
=
cls
(
pkt
)
except
KeyboardInterrupt
:
raise
except
:
if
conf
.
debug_dissector
:
raise
pkt
=
conf
.
raw_layer
(
pkt
)
pkt
.
time
=
ts
return
pkt
def
nonblock_recv
(
self
):
self
.
ins
.
setnonblock
(
1
)
p
=
self
.
recv
(
MTU
)
self
.
ins
.
setnonblock
(
0
)
return
p
def
close
(
self
):
if
hasattr
(
self
,
"
ins
"
):
self
.
ins
.
close
()
if
hasattr
(
self
,
"
outs
"
):
self
.
outs
.
close
()
class
L3pcapSocket
(
L2pcapSocket
):
#def __init__(self, iface = None, type = ETH_P_ALL, filter=None, nofilter=0):
# L2pcapSocket.__init__(self, iface, type, filter, nofilter)
def
recv
(
self
,
x
=
MTU
):
r
=
L2pcapSocket
.
recv
(
self
,
x
)
if
r
:
return
r
.
payload
else
:
return
def
send
(
self
,
x
):
cls
=
conf
.
l2types
[
1
]
sx
=
str
(
cls
()
/
x
)
if
hasattr
(
x
,
"
sent_time
"
):
x
.
sent_time
=
time
.
time
()
return
self
.
ins
.
send
(
sx
)
conf
.
L2socket
=
L2pcapSocket
conf
.
L3socket
=
L3pcapSocket
if
conf
.
use_pcap
:
if
conf
.
use_pcap
:
...
...
This diff is collapsed.
Click to expand it.
scapy/arch/windows/__init__.py
+
236
−
185
View file @
0dfb5bfb
...
@@ -7,19 +7,33 @@
...
@@ -7,19 +7,33 @@
Customizations needed to support Microsoft Windows.
Customizations needed to support Microsoft Windows.
"""
"""
import
os
,
re
,
sys
,
socket
,
time
import
os
,
re
,
sys
,
socket
,
time
,
itertools
import
subprocess
as
sp
from
glob
import
glob
from
glob
import
glob
from
scapy.config
import
conf
,
ConfClass
from
scapy.config
import
conf
,
ConfClass
from
scapy.error
import
Scapy_Exception
,
log_loading
,
log_runtime
from
scapy.error
import
Scapy_Exception
,
log_loading
,
log_runtime
from
scapy.utils
import
atol
,
inet_aton
,
inet_ntoa
,
PcapReader
from
scapy.utils
import
atol
,
itom
,
inet_aton
,
inet_ntoa
,
PcapReader
from
scapy.base_classes
import
Gen
,
Net
,
SetGen
from
scapy.base_classes
import
Gen
,
Net
,
SetGen
import
scapy.plist
as
plist
import
scapy.plist
as
plist
from
scapy.sendrecv
import
debug
,
srp1
from
scapy.sendrecv
import
debug
,
srp1
from
scapy.layers.l2
import
Ether
,
ARP
from
scapy.layers.l2
import
Ether
,
ARP
from
scapy.data
import
MTU
,
ETHER_BROADCAST
,
ETH_P_ARP
from
scapy.data
import
MTU
,
ETHER_BROADCAST
,
ETH_P_ARP
conf
.
use_pcap
=
1
conf
.
use_pcap
=
False
conf
.
use_dnet
=
1
conf
.
use_dnet
=
False
conf
.
use_winpcapy
=
True
#hot-patching socket for missing variables on Windows
import
socket
if
not
hasattr
(
socket
,
'
IPPROTO_IPIP
'
):
socket
.
IPPROTO_IPIP
=
4
if
not
hasattr
(
socket
,
'
IPPROTO_AH
'
):
socket
.
IPPROTO_AH
=
51
if
not
hasattr
(
socket
,
'
IPPROTO_ESP
'
):
socket
.
IPPROTO_ESP
=
50
from
scapy.arch
import
pcapdnet
from
scapy.arch
import
pcapdnet
from
scapy.arch.pcapdnet
import
*
from
scapy.arch.pcapdnet
import
*
...
@@ -69,119 +83,136 @@ class WinProgPath(ConfClass):
...
@@ -69,119 +83,136 @@ class WinProgPath(ConfClass):
conf
.
prog
=
WinProgPath
()
conf
.
prog
=
WinProgPath
()
import
_winreg
class
PcapNameNotFoundError
(
Scapy_Exception
):
class
PcapNameNotFoundError
(
Scapy_Exception
):
pass
pass
import
platform
def
is_interface_valid
(
iface
):
if
"
guid
"
in
iface
and
iface
[
"
guid
"
]:
return
True
return
False
def
get_windows_if_list
():
if
platform
.
release
()
==
"
post2008Server
"
or
platform
.
release
()
==
"
8
"
:
# This works only starting from Windows 8/2012 and up. For older Windows another solution is needed
ps
=
sp
.
Popen
([
'
powershell
'
,
'
Get-NetAdapter
'
,
'
|
'
,
'
select Name, InterfaceIndex, InterfaceDescription, InterfaceGuid, MacAddress
'
,
'
|
'
,
'
fl
'
],
stdout
=
sp
.
PIPE
,
universal_newlines
=
True
)
else
:
ps
=
sp
.
Popen
([
'
powershell
'
,
'
Get-WmiObject
'
,
'
Win32_NetworkAdapter
'
,
'
|
'
,
'
select Name, InterfaceIndex, InterfaceDescription, GUID, MacAddress
'
,
'
|
'
,
'
fl
'
],
stdout
=
sp
.
PIPE
,
universal_newlines
=
True
)
#no solution implemented for xp
stdout
,
stdin
=
ps
.
communicate
()
current_interface
=
None
interface_list
=
[]
for
i
in
stdout
.
split
(
'
\n
'
):
if
not
i
.
strip
():
continue
if
i
.
find
(
'
:
'
)
<
0
:
continue
name
,
value
=
[
j
.
strip
()
for
j
in
i
.
split
(
'
:
'
,
1
)
]
if
name
==
'
Name
'
:
if
current_interface
and
is_interface_valid
(
current_interface
):
interface_list
.
append
(
current_interface
)
current_interface
=
{}
current_interface
[
'
name
'
]
=
value
elif
name
==
'
InterfaceIndex
'
:
current_interface
[
'
win_index
'
]
=
int
(
value
)
elif
name
==
'
InterfaceDescription
'
:
current_interface
[
'
description
'
]
=
value
elif
name
==
'
InterfaceGuid
'
:
current_interface
[
'
guid
'
]
=
value
elif
name
==
'
GUID
'
:
current_interface
[
'
guid
'
]
=
value
elif
name
==
'
MacAddress
'
:
current_interface
[
'
mac
'
]
=
'
:
'
.
join
([
j
for
j
in
value
.
split
(
'
-
'
)])
if
current_interface
and
is_interface_valid
(
current_interface
):
interface_list
.
append
(
current_interface
)
return
interface_list
def
get_ip_from_name
(
ifname
,
v6
=
False
):
ps
=
sp
.
Popen
([
'
powershell
'
,
'
Get-WmiObject
'
,
'
Win32_NetworkAdapterConfiguration
'
,
'
|
'
,
'
select Description, IPAddress
'
,
'
|
'
,
'
fl
'
],
stdout
=
sp
.
PIPE
,
universal_newlines
=
True
)
stdout
,
stdin
=
ps
.
communicate
()
selected
=
False
for
i
in
stdout
.
split
(
'
\n
'
):
if
not
i
.
strip
():
continue
if
i
.
find
(
'
:
'
)
<
0
:
continue
name
,
value
=
[
j
.
strip
()
for
j
in
i
.
split
(
'
:
'
,
1
)
]
if
name
==
"
Description
"
and
value
.
strip
()
==
ifname
.
strip
():
selected
=
True
elif
selected
:
if
v6
:
return
value
.
split
(
"
,
"
,
1
)[
1
].
strip
(
'
{}
'
).
strip
()
else
:
return
value
.
split
(
"
,
"
,
1
)[
0
].
strip
(
'
{}
'
).
strip
()
class
NetworkInterface
(
object
):
class
NetworkInterface
(
object
):
"""
A network interface of your local host
"""
"""
A network interface of your local host
"""
def
__init__
(
self
,
d
netdict
=
None
):
def
__init__
(
self
,
d
ata
=
None
):
self
.
name
=
None
self
.
name
=
None
self
.
ip
=
None
self
.
ip
=
None
self
.
mac
=
None
self
.
mac
=
None
self
.
pcap_name
=
None
self
.
pcap_name
=
None
self
.
win_name
=
None
self
.
description
=
None
self
.
uuid
=
None
self
.
data
=
data
self
.
dnetdict
=
dnetdict
if
data
is
not
None
:
if
dnetdict
is
not
None
:
self
.
update
(
data
)
self
.
update
(
dnetdict
)
def
update
(
self
,
d
netdict
):
def
update
(
self
,
d
ata
):
"""
Update info about network interface according to given dnet dictionary
"""
"""
Update info about network interface according to given dnet dictionary
"""
self
.
name
=
dnetdict
[
"
name
"
]
self
.
name
=
data
[
"
name
"
]
self
.
description
=
data
[
'
description
'
]
self
.
win_index
=
data
[
'
win_index
'
]
# Other attributes are optional
# Other attributes are optional
self
.
_update_pcapdata
()
try
:
try
:
self
.
ip
=
socket
.
inet_ntoa
(
dnetdict
[
"
addr
"
].
ip
)
self
.
ip
=
socket
.
inet_ntoa
(
get_if_raw_addr
(
data
[
'
guid
'
])
)
except
(
KeyError
,
AttributeError
,
NameError
):
except
(
KeyError
,
AttributeError
,
NameError
):
pass
pass
try
:
try
:
self
.
mac
=
dnetdict
[
"
link_addr
"
]
if
not
self
.
ip
:
self
.
ip
=
get_ip_from_name
(
data
[
'
name
'
])
except
(
KeyError
,
AttributeError
,
NameError
)
as
e
:
print
e
try
:
self
.
mac
=
data
[
'
mac
'
]
except
KeyError
:
except
KeyError
:
pass
pass
self
.
_update_pcapdata
()
def
_update_pcapdata
(
self
):
def
_update_pcapdata
(
self
):
"""
Supplement more info from pypcap and the Windows registry
"""
for
i
in
winpcapy_get_if_list
():
if
i
.
endswith
(
self
.
data
[
'
guid
'
]):
# XXX: We try eth0 - eth29 by bruteforce and match by IP address,
self
.
pcap_name
=
i
# because only the IP is available in both pypcap and dnet.
return
# This may not work with unorthodox network configurations and is
# slow because we have to walk through the Windows registry.
for
n
in
xrange
(
30
):
guess
=
"
eth%s
"
%
n
win_name
=
pcapdnet
.
pcap
.
ex_name
(
guess
)
if
win_name
.
endswith
(
"
}
"
):
try
:
uuid
=
win_name
[
win_name
.
index
(
"
{
"
):
win_name
.
index
(
"
}
"
)
+
1
]
keyname
=
r
"
SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\%s
"
%
uuid
try
:
key
=
_winreg
.
OpenKey
(
_winreg
.
HKEY_LOCAL_MACHINE
,
keyname
)
except
WindowsError
:
log_loading
.
debug
(
"
Couldn
'
t open
'
HKEY_LOCAL_MACHINE
\\
%s
'
(for guessed pcap iface name
'
%s
'
).
"
%
(
keyname
,
guess
))
continue
try
:
fixed_ip
=
_winreg
.
QueryValueEx
(
key
,
"
IPAddress
"
)[
0
][
0
].
encode
(
"
utf-8
"
)
except
(
WindowsError
,
UnicodeDecodeError
,
IndexError
):
fixed_ip
=
None
try
:
dhcp_ip
=
_winreg
.
QueryValueEx
(
key
,
"
DhcpIPAddress
"
)[
0
].
encode
(
"
utf-8
"
)
except
(
WindowsError
,
UnicodeDecodeError
,
IndexError
):
dhcp_ip
=
None
# "0.0.0.0" or None means the value is not set (at least not correctly).
# If both fixed_ip and dhcp_ip are set, fixed_ip takes precedence
if
fixed_ip
is
not
None
and
fixed_ip
!=
"
0.0.0.0
"
:
ip
=
fixed_ip
elif
dhcp_ip
is
not
None
and
dhcp_ip
!=
"
0.0.0.0
"
:
ip
=
dhcp_ip
else
:
continue
except
IOError
:
continue
else
:
if
ip
==
self
.
ip
:
self
.
pcap_name
=
guess
self
.
win_name
=
win_name
self
.
uuid
=
uuid
break
else
:
raise
PcapNameNotFoundError
raise
PcapNameNotFoundError
def
__repr__
(
self
):
def
__repr__
(
self
):
return
"
<%s: %s %s %s pcap_name=%s
win_name
=%s>
"
%
(
self
.
__class__
.
__name__
,
return
"
<%s: %s %s %s pcap_name=%s
description
=%s>
"
%
(
self
.
__class__
.
__name__
,
self
.
name
,
self
.
ip
,
self
.
mac
,
self
.
pcap_name
,
self
.
win_name
)
self
.
name
,
self
.
ip
,
self
.
mac
,
repr
(
self
.
pcap_name
)
,
repr
(
self
.
description
)
)
from
UserDict
import
Iterable
UserDict
from
UserDict
import
UserDict
class
NetworkInterfaceDict
(
Iterable
UserDict
):
class
NetworkInterfaceDict
(
UserDict
):
"""
Store information about network interfaces and convert between names
"""
"""
Store information about network interfaces and convert between names
"""
def
load_from_powershell
(
self
):
def
load_from_dnet
(
self
):
for
i
in
get_windows_if_list
():
"""
Populate interface table via dnet
"""
for
i
in
pcapdnet
.
dnet
.
intf
():
try
:
try
:
# XXX: Only Ethernet for the moment: localhost is not supported by dnet and pcap
interface
=
NetworkInterface
(
i
)
# We only take interfaces that have an IP address, because the IP
self
.
data
[
interface
.
name
]
=
interface
# is used for the mapping between dnet and pcap interface names
# and this significantly improves Scapy's startup performance
if
i
[
"
name
"
].
startswith
(
"
eth
"
)
and
"
addr
"
in
i
:
self
.
data
[
i
[
"
name
"
]]
=
NetworkInterface
(
i
)
except
(
KeyError
,
PcapNameNotFoundError
):
except
(
KeyError
,
PcapNameNotFoundError
):
pass
pass
if
len
(
self
.
data
)
==
0
:
if
len
(
self
.
data
)
==
0
:
log_loading
.
warning
(
"
No match between your pcap and
dnet
network interfaces found.
"
log_loading
.
warning
(
"
No match between your pcap and
windows
network interfaces found.
"
"
You probably won
'
t be able to send packets.
"
"
You probably won
'
t be able to send packets.
"
"
Deactivating unneeded interfaces and restarting Scapy might help.
"
)
"
Deactivating unneeded interfaces and restarting Scapy might help.
"
"
Check your winpcap and powershell installation, and access rights.
"
)
def
pcap_name
(
self
,
devname
):
def
pcap_name
(
self
,
devname
):
"""
Return pypcap device name for given libdnet/Scapy device name
"""
Return pcap device name for given Windows device name.
"""
This mapping is necessary because pypcap numbers the devices differently.
"""
try
:
try
:
pcap_name
=
self
.
data
[
devname
].
pcap_name
pcap_name
=
self
.
data
[
devname
].
pcap_name
...
@@ -191,30 +222,37 @@ class NetworkInterfaceDict(IterableUserDict):
...
@@ -191,30 +222,37 @@ class NetworkInterfaceDict(IterableUserDict):
return
pcap_name
return
pcap_name
def
devname
(
self
,
pcap_name
):
def
devname
(
self
,
pcap_name
):
"""
Return libdnet/Scapy device name for given pypcap device name
"""
Return Windows device name for given pcap device name.
"""
This mapping is necessary because pypcap numbers the devices differently.
"""
for
devname
,
iface
in
self
.
items
():
for
devname
,
iface
in
self
.
items
():
if
iface
.
pcap_name
==
pcap_name
:
if
iface
.
pcap_name
==
pcap_name
:
return
iface
.
name
return
iface
.
name
raise
ValueError
(
"
Unknown pypcap network interface %r
"
%
pcap_name
)
raise
ValueError
(
"
Unknown pypcap network interface %r
"
%
pcap_name
)
def
devname_from_index
(
self
,
if_index
):
"""
Return interface name from interface index
"""
for
devname
,
iface
in
self
.
items
():
if
iface
.
win_index
==
if_index
:
return
iface
.
name
raise
ValueError
(
"
Unknown network interface index %r
"
%
if_index
)
def
show
(
self
,
resolve_mac
=
True
):
def
show
(
self
,
resolve_mac
=
True
):
"""
Print list of available network interfaces in human readable form
"""
"""
Print list of available network interfaces in human readable form
"""
print
"
%s %s %s
"
%
(
"
IFACE
"
.
ljust
(
5
),
"
IP
"
.
ljust
(
15
),
"
MAC
"
)
print
"
%s %s
%s
%s
"
%
(
"
INDEX
"
.
ljust
(
5
),
"
IFACE
"
.
ljust
(
3
5
),
"
IP
"
.
ljust
(
15
),
"
MAC
"
)
for
iface_name
in
sorted
(
self
.
data
.
keys
()):
for
iface_name
in
sorted
(
self
.
data
.
keys
()):
dev
=
self
.
data
[
iface_name
]
dev
=
self
.
data
[
iface_name
]
mac
=
str
(
dev
.
mac
)
mac
=
dev
.
mac
if
resolve_mac
:
if
resolve_mac
:
mac
=
conf
.
manufdb
.
_resolve_MAC
(
mac
)
mac
=
conf
.
manufdb
.
_resolve_MAC
(
mac
)
print
"
%s %s %s
"
%
(
str
(
dev
.
name
).
ljust
(
5
),
str
(
dev
.
ip
).
ljust
(
15
),
mac
)
print
"
%s %s
%s
%s
"
%
(
str
(
dev
.
win_index
).
ljust
(
5
),
str
(
dev
.
name
).
ljust
(
3
5
),
str
(
dev
.
ip
).
ljust
(
15
),
mac
)
ifaces
=
NetworkInterfaceDict
()
ifaces
=
NetworkInterfaceDict
()
ifaces
.
load_from_
dnet
()
ifaces
.
load_from_
powershell
()
def
pcap_name
(
devname
):
def
pcap_name
(
devname
):
"""
Return pypcap device name for given libdnet/Scapy device name
"""
"""
Return pypcap device name for given libdnet/Scapy device name
"""
if
type
(
devname
)
is
NetworkInterface
:
return
devname
.
pcap_name
try
:
try
:
pcap_name
=
ifaces
.
pcap_name
(
devname
)
pcap_name
=
ifaces
.
pcap_name
(
devname
)
except
ValueError
:
except
ValueError
:
...
@@ -226,6 +264,10 @@ def devname(pcap_name):
...
@@ -226,6 +264,10 @@ def devname(pcap_name):
"""
Return libdnet/Scapy device name for given pypcap device name
"""
"""
Return libdnet/Scapy device name for given pypcap device name
"""
return
ifaces
.
devname
(
pcap_name
)
return
ifaces
.
devname
(
pcap_name
)
def
devname_from_index
(
if_index
):
"""
Return Windows adapter name for given Windows interface index
"""
return
ifaces
.
devname_from_index
(
if_index
)
def
show_interfaces
(
resolve_mac
=
True
):
def
show_interfaces
(
resolve_mac
=
True
):
"""
Print list of available network interfaces
"""
"""
Print list of available network interfaces
"""
return
ifaces
.
show
(
resolve_mac
)
return
ifaces
.
show
(
resolve_mac
)
...
@@ -233,86 +275,93 @@ def show_interfaces(resolve_mac=True):
...
@@ -233,86 +275,93 @@ def show_interfaces(resolve_mac=True):
_orig_open_pcap
=
pcapdnet
.
open_pcap
_orig_open_pcap
=
pcapdnet
.
open_pcap
pcapdnet
.
open_pcap
=
lambda
iface
,
*
args
,
**
kargs
:
_orig_open_pcap
(
pcap_name
(
iface
),
*
args
,
**
kargs
)
pcapdnet
.
open_pcap
=
lambda
iface
,
*
args
,
**
kargs
:
_orig_open_pcap
(
pcap_name
(
iface
),
*
args
,
**
kargs
)
_orig_get_if_raw_hwaddr
=
pcapdnet
.
get_if_raw_hwaddr
pcapdnet
.
get_if_raw_hwaddr
=
lambda
iface
,
*
args
,
**
kargs
:
(
ARPHDR_ETHER
,
''
.
join
([
chr
(
int
(
i
,
16
))
for
i
in
ifaces
[
iface
].
mac
.
split
(
'
:
'
)
]))
get_if_raw_hwaddr
=
pcapdnet
.
get_if_raw_hwaddr
def
read_routes_7
():
routes
=
[]
ps
=
sp
.
Popen
([
'
powershell
'
,
'
Get-WmiObject
'
,
'
win32_IP4RouteTable
'
,
'
|
'
,
'
select Name,Mask,NextHop,InterfaceIndex
'
,
'
|
'
,
'
fl
'
],
stdout
=
sp
.
PIPE
,
universal_newlines
=
True
)
stdout
,
stdin
=
ps
.
communicate
()
dest
=
None
mask
=
None
gw
=
None
ifIndex
=
None
for
i
in
stdout
.
split
(
'
\n
'
):
if
not
i
.
strip
():
continue
if
i
.
find
(
'
:
'
)
<
0
:
continue
name
,
value
=
[
j
.
strip
().
lower
()
for
j
in
i
.
split
(
'
:
'
,
1
)
]
if
name
==
"
name
"
:
dest
=
atol
(
value
)
elif
name
==
"
mask
"
:
mask
=
atol
(
value
)
elif
name
==
"
nexthop
"
:
gw
=
value
elif
name
==
"
interfaceindex
"
:
ifIndex
=
value
try
:
iface
=
devname_from_index
(
int
(
ifIndex
))
except
ValueError
:
continue
addr
=
ifaces
[
iface
].
ip
routes
.
append
((
dest
,
mask
,
gw
,
iface
,
addr
))
return
routes
def
read_routes
():
def
read_routes
():
ok
=
0
routes
=
[]
routes
=
[]
ip
=
'
(\d+\.\d+\.\d+\.\d+)
'
try
:
# On Vista and Windows 7 the gateway can be IP or 'On-link'.
if
platform
.
release
()
==
"
post2008Server
"
or
platform
.
release
()
==
"
8
"
:
# But the exact 'On-link' string depends on the locale, so we allow any text.
routes
=
read_routes_post2008
()
gw_pattern
=
'
(.+)
'
else
:
routes
=
read_routes_7
()
except
Exception
as
e
:
log_loading
.
warning
(
"
Error building scapy routing table : %s
"
%
str
(
e
))
else
:
if
not
routes
:
log_loading
.
warning
(
"
No default IPv4 routes found. Your Windows release may no be supported and you have to enter your routes manually
"
)
return
routes
def
read_routes_post2008
():
routes
=
[]
if_index
=
'
(\d+)
'
dest
=
'
(\d+\.\d+\.\d+\.\d+)/(\d+)
'
next_hop
=
'
(\d+\.\d+\.\d+\.\d+)
'
metric_pattern
=
"
(\d+)
"
metric_pattern
=
"
(\d+)
"
delim
=
"
\s+
"
# The columns are separated by whitespace
delim
=
"
\s+
"
# The columns are separated by whitespace
netstat_line
=
delim
.
join
([
i
p
,
ip
,
gw_pattern
,
i
p
,
metric_pattern
])
netstat_line
=
delim
.
join
([
i
f_index
,
dest
,
next_ho
p
,
metric_pattern
])
pattern
=
re
.
compile
(
netstat_line
)
pattern
=
re
.
compile
(
netstat_line
)
f
=
os
.
popen
(
"
netstat -rn
"
)
# This works only starting from Windows 8/2012 and up. For older Windows another solution is needed
for
l
in
f
.
readlines
():
ps
=
sp
.
Popen
([
'
powershell
'
,
'
Get-NetRoute
'
,
'
-AddressFamily IPV4
'
,
'
|
'
,
'
select ifIndex, DestinationPrefix, NextHop, RouteMetric
'
],
stdout
=
sp
.
PIPE
,
universal_newlines
=
True
)
stdout
,
stdin
=
ps
.
communicate
()
for
l
in
stdout
.
split
(
'
\n
'
):
match
=
re
.
search
(
pattern
,
l
)
match
=
re
.
search
(
pattern
,
l
)
if
match
:
if
match
:
dest
=
match
.
group
(
1
)
mask
=
match
.
group
(
2
)
gw
=
match
.
group
(
3
)
netif
=
match
.
group
(
4
)
metric
=
match
.
group
(
5
)
try
:
try
:
i
ntf
=
pcapdnet
.
dnet
.
intf
().
get_dst
(
pcapdnet
.
dnet
.
addr
(
type
=
2
,
addrtxt
=
dest
))
i
face
=
devname_from_index
(
int
(
match
.
group
(
1
)
))
except
OSError
:
addr
=
ifaces
[
iface
].
ip
log_loading
.
warning
(
"
Building Scapy
'
s routing table: Couldn
'
t get outgoing interface for destination %s
"
%
dest
)
except
:
continue
continue
if
not
intf
.
has_key
(
"
addr
"
):
dest
=
atol
(
match
.
group
(
2
))
break
mask
=
itom
(
int
(
match
.
group
(
3
)))
addr
=
str
(
intf
[
"
addr
"
])
gw
=
match
.
group
(
4
)
addr
=
addr
.
split
(
"
/
"
)[
0
]
# try:
# intf = pcapdnet.dnet.intf().get_dst(pcapdnet.dnet.addr(type=2, addrtxt=dest))
dest
=
atol
(
dest
)
# except OSError:
mask
=
atol
(
mask
)
# log_loading.warning("Building Scapy's routing table: Couldn't get outgoing interface for destination %s" % dest)
# If the gateway is no IP we assume it's on-link
# continue
gw_ipmatch
=
re
.
search
(
'
\d+\.\d+\.\d+\.\d+
'
,
gw
)
routes
.
append
((
dest
,
mask
,
gw
,
iface
,
addr
))
if
gw_ipmatch
:
gw
=
gw_ipmatch
.
group
(
0
)
else
:
gw
=
netif
routes
.
append
((
dest
,
mask
,
gw
,
str
(
intf
[
"
name
"
]),
addr
))
f
.
close
()
return
routes
return
routes
def
read_routes6
():
def
read_routes6
():
return
[]
return
[]
def
getmacbyip
(
ip
,
chainCC
=
0
):
if
conf
.
interactive_shell
!=
'
ipython
'
:
"""
Return MAC address corresponding to a given IP address
"""
try
:
if
isinstance
(
ip
,
Net
):
__IPYTHON__
ip
=
iter
(
ip
).
next
()
except
NameError
:
tmp
=
map
(
ord
,
inet_aton
(
ip
))
if
(
tmp
[
0
]
&
0xf0
)
==
0xe0
:
# mcast @
return
"
01:00:5e:%.2x:%.2x:%.2x
"
%
(
tmp
[
1
]
&
0x7f
,
tmp
[
2
],
tmp
[
3
])
iff
,
a
,
gw
=
conf
.
route
.
route
(
ip
)
if
(
(
iff
==
LOOPBACK_NAME
)
or
(
ip
==
conf
.
route
.
get_if_bcast
(
iff
))
):
return
"
ff:ff:ff:ff:ff:ff
"
# Windows uses local IP instead of 0.0.0.0 to represent locally reachable addresses
ifip
=
str
(
pcapdnet
.
dnet
.
intf
().
get
(
iff
)[
'
addr
'
])
if
gw
!=
ifip
.
split
(
'
/
'
)[
0
]:
ip
=
gw
mac
=
conf
.
netcache
.
arp_cache
.
get
(
ip
)
if
mac
:
return
mac
res
=
srp1
(
Ether
(
dst
=
ETHER_BROADCAST
)
/
ARP
(
op
=
"
who-has
"
,
pdst
=
ip
),
type
=
ETH_P_ARP
,
iface
=
iff
,
timeout
=
2
,
verbose
=
0
,
chainCC
=
chainCC
,
nofilter
=
1
)
if
res
is
not
None
:
mac
=
res
.
payload
.
hwsrc
conf
.
netcache
.
arp_cache
[
ip
]
=
mac
return
mac
return
None
import
scapy.layers.l2
scapy
.
layers
.
l2
.
getmacbyip
=
getmacbyip
try
:
try
:
import
readline
import
readline
console
=
readline
.
GetOutputFile
()
console
=
readline
.
GetOutputFile
()
...
@@ -323,10 +372,6 @@ else:
...
@@ -323,10 +372,6 @@ else:
orig_stdout
=
sys
.
stdout
orig_stdout
=
sys
.
stdout
sys
.
stdout
=
console
sys
.
stdout
=
console
def
sndrcv
(
pks
,
pkt
,
timeout
=
2
,
inter
=
0
,
verbose
=
None
,
chainCC
=
0
,
retry
=
0
,
multi
=
0
):
def
sndrcv
(
pks
,
pkt
,
timeout
=
2
,
inter
=
0
,
verbose
=
None
,
chainCC
=
0
,
retry
=
0
,
multi
=
0
):
if
not
isinstance
(
pkt
,
Gen
):
if
not
isinstance
(
pkt
,
Gen
):
pkt
=
SetGen
(
pkt
)
pkt
=
SetGen
(
pkt
)
...
@@ -395,7 +440,6 @@ def sndrcv(pks, pkt, timeout = 2, inter = 0, verbose=None, chainCC=0, retry=0, m
...
@@ -395,7 +440,6 @@ def sndrcv(pks, pkt, timeout = 2, inter = 0, verbose=None, chainCC=0, retry=0, m
else
:
else
:
stoptime
=
0
stoptime
=
0
remaintime
=
None
remaintime
=
None
inmask
=
[
pks
.
ins
.
fd
]
try
:
try
:
try
:
try
:
while
1
:
while
1
:
...
@@ -442,9 +486,9 @@ def sndrcv(pks, pkt, timeout = 2, inter = 0, verbose=None, chainCC=0, retry=0, m
...
@@ -442,9 +486,9 @@ def sndrcv(pks, pkt, timeout = 2, inter = 0, verbose=None, chainCC=0, retry=0, m
finally
:
finally
:
pass
pass
remain
=
reduce
(
list
.
__add__
,
hsent
.
values
()
,
[
])
remain
=
list
(
itertools
.
chain
(
*
[
i
for
i
in
hsent
.
values
()
])
)
if
multi
:
if
multi
:
remain
=
filter
(
lambda
p
:
not
hasattr
(
p
,
'
_answered
'
)
,
remain
);
remain
=
[
p
for
p
in
remain
if
not
hasattr
(
p
,
'
_answered
'
)
]
if
autostop
and
len
(
remain
)
>
0
and
len
(
remain
)
!=
len
(
tobesent
):
if
autostop
and
len
(
remain
)
>
0
and
len
(
remain
)
!=
len
(
tobesent
):
retry
=
autostop
retry
=
autostop
...
@@ -475,7 +519,7 @@ scapy.sendrecv.sndrcv = sndrcv
...
@@ -475,7 +519,7 @@ scapy.sendrecv.sndrcv = sndrcv
def
sniff
(
count
=
0
,
store
=
1
,
offline
=
None
,
prn
=
None
,
lfilter
=
None
,
L2socket
=
None
,
timeout
=
None
,
*
arg
,
**
karg
):
def
sniff
(
count
=
0
,
store
=
1
,
offline
=
None
,
prn
=
None
,
lfilter
=
None
,
L2socket
=
None
,
timeout
=
None
,
*
arg
,
**
karg
):
"""
Sniff packets
"""
Sniff packets
sniff([count=0,] [prn=None,] [store=1,] [offline=None,] [lfilter=None,] + L2ListenSocket args) -> list of packets
sniff([count=0,] [prn=None,] [store=1,] [offline=None,] [lfilter=None,] + L2ListenSocket args) -> list of packets
Select interface to sniff by setting conf.iface. Use show_interfaces() to see interface names.
count: number of packets to capture. 0 means infinity
count: number of packets to capture. 0 means infinity
store: wether to store sniffed packets or discard them
store: wether to store sniffed packets or discard them
prn: function to apply to each packet. If something is returned,
prn: function to apply to each packet. If something is returned,
...
@@ -491,6 +535,7 @@ L2socket: use the provided L2socket
...
@@ -491,6 +535,7 @@ L2socket: use the provided L2socket
c
=
0
c
=
0
if
offline
is
None
:
if
offline
is
None
:
log_runtime
.
info
(
'
Sniffing on %s
'
%
conf
.
iface
)
if
L2socket
is
None
:
if
L2socket
is
None
:
L2socket
=
conf
.
L2listen
L2socket
=
conf
.
L2listen
s
=
L2socket
(
type
=
ETH_P_ALL
,
*
arg
,
**
karg
)
s
=
L2socket
(
type
=
ETH_P_ALL
,
*
arg
,
**
karg
)
...
@@ -533,11 +578,17 @@ L2socket: use the provided L2socket
...
@@ -533,11 +578,17 @@ L2socket: use the provided L2socket
import
scapy.sendrecv
import
scapy.sendrecv
scapy
.
sendrecv
.
sniff
=
sniff
scapy
.
sendrecv
.
sniff
=
sniff
def
get_if_list
():
return
sorted
(
ifaces
.
keys
())
def
get_working_if
():
def
get_working_if
():
try
:
try
:
return
devname
(
pcap
.
lookupdev
())
if
'
Ethernet
'
in
ifaces
and
ifaces
[
'
Ethernet
'
].
ip
!=
'
0.0.0.0
'
:
except
Exception
:
return
'
Ethernet
'
return
'
lo0
'
elif
'
Wi-Fi
'
in
ifaces
and
ifaces
[
'
Wi-Fi
'
].
ip
!=
'
0.0.0.0
'
:
return
'
Wi-Fi
'
elif
len
(
ifaces
)
>
0
:
return
ifaces
[
list
(
ifaces
.
keys
())[
0
]]
else
:
return
LOOPBACK_NAME
except
:
return
LOOPBACK_NAME
conf
.
iface
=
get_working_if
()
This diff is collapsed.
Click to expand it.
scapy/config.py
100644 → 100755
+
1
−
0
View file @
0dfb5bfb
...
@@ -360,6 +360,7 @@ extensions_paths: path or list of paths where extensions are to be looked for
...
@@ -360,6 +360,7 @@ extensions_paths: path or list of paths where extensions are to be looked for
emph
=
Emphasize
()
emph
=
Emphasize
()
use_pcap
=
False
use_pcap
=
False
use_dnet
=
False
use_dnet
=
False
use_winpcapy
=
False
ipv6_enabled
=
socket
.
has_ipv6
ipv6_enabled
=
socket
.
has_ipv6
ethertypes
=
ETHER_TYPES
ethertypes
=
ETHER_TYPES
protocols
=
IP_PROTOS
protocols
=
IP_PROTOS
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment