Skip to content

Commit 00f66f1

Browse files
committed
Fix handle inheritance for Python2 (more appropriate and safe version of #1138 hack, fixes #1136)
Fix an error of '_windows_title()' for Py2
1 parent 71c23da commit 00f66f1

1 file changed

Lines changed: 64 additions & 29 deletions

File tree

scapy/arch/windows/__init__.py

Lines changed: 64 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@
1212
import os, re, sys, socket, time, itertools, platform
1313
import subprocess as sp
1414
from glob import glob
15-
import ctypes, tempfile
15+
import ctypes
16+
from ctypes import wintypes
17+
import tempfile
1618
from threading import Thread, Event
1719

1820
import scapy
@@ -27,6 +29,18 @@
2729
from scapy.modules.six.moves import range, zip, input, winreg
2830
from scapy.compat import plain_str
2931

32+
_winapi_SetConsoleTitle = ctypes.windll.kernel32.SetConsoleTitleW
33+
_winapi_SetConsoleTitle.restype = wintypes.BOOL
34+
_winapi_SetConsoleTitle.argtypes = [wintypes.LPWSTR]
35+
36+
_winapi_GetHandleInformation = ctypes.windll.kernel32.GetHandleInformation
37+
_winapi_GetHandleInformation.restype = wintypes.BOOL
38+
_winapi_GetHandleInformation.argtypes = [wintypes.HANDLE, ctypes.POINTER(wintypes.DWORD)]
39+
40+
_winapi_SetHandleInformation = ctypes.windll.kernel32.SetHandleInformation
41+
_winapi_SetHandleInformation.restype = wintypes.BOOL
42+
_winapi_SetHandleInformation.argtypes = [wintypes.HANDLE, wintypes.DWORD, wintypes.DWORD]
43+
3044
conf.use_pcap = False
3145
conf.use_dnet = False
3246
conf.use_winpcapy = True
@@ -80,58 +94,79 @@ def _windows_title(title=None):
8094
"""Updates the terminal title with the default one or with `title`
8195
if provided."""
8296
if conf.interactive:
83-
title = title or "Scapy v" + conf.version
84-
ctypes.windll.kernel32.SetConsoleTitleW(title)
97+
_winapi_SetConsoleTitle(title or "Scapy v{}".format(conf.version))
8598

86-
def _suppress_file_handles_inheritance(r=100):
99+
def _suppress_file_handles_inheritance(r=1000):
87100
"""HACK: python 2.7 file descriptors.
88101
89102
This magic hack fixes https://bugs.python.org/issue19575
103+
and https://github.com/secdev/scapy/issues/1136
90104
by suppressing the HANDLE_FLAG_INHERIT flag to a range of
91105
already opened file descriptors.
106+
Bug was fixed on python 3.4+
92107
"""
93-
# See https://github.com/secdev/scapy/issues/1136
108+
if sys.version_info[0:2] >= (3, 4):
109+
return []
110+
94111
import stat
95-
from ctypes import windll, wintypes
96112
from msvcrt import get_osfhandle
97113

98114
HANDLE_FLAG_INHERIT = 0x00000001
99115

116+
handles = []
100117
for fd in range(r):
101118
try:
102119
s = os.fstat(fd)
103120
except OSError:
104121
continue
105122
if stat.S_ISREG(s.st_mode):
106-
handle = wintypes.HANDLE(get_osfhandle(fd))
107-
mask = wintypes.DWORD(HANDLE_FLAG_INHERIT)
108-
flags = wintypes.DWORD(0)
109-
windll.kernel32.SetHandleInformation(handle, mask, flags)
123+
osf_handle = get_osfhandle(fd)
124+
flags = wintypes.DWORD()
125+
_winapi_GetHandleInformation(osf_handle, flags)
126+
if flags.value & HANDLE_FLAG_INHERIT:
127+
_winapi_SetHandleInformation(osf_handle, HANDLE_FLAG_INHERIT, 0)
128+
handles.append(osf_handle)
129+
130+
return handles
131+
132+
def _restore_file_handles_inheritance(handles):
133+
"""HACK: python 2.7 file descriptors.
134+
135+
This magic hack fixes https://bugs.python.org/issue19575
136+
and https://github.com/secdev/scapy/issues/1136
137+
by suppressing the HANDLE_FLAG_INHERIT flag to a range of
138+
already opened file descriptors.
139+
Bug was fixed on python 3.4+
140+
"""
141+
if sys.version_info[0:2] >= (3, 4):
142+
return
143+
144+
HANDLE_FLAG_INHERIT = 0x00000001
145+
146+
for osf_handle in handles:
147+
try:
148+
_winapi_SetHandleInformation(osf_handle, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)
149+
except (ctypes.WinError, WindowsError, OSError):
150+
pass
110151

111152
class _PowershellManager(Thread):
112153
"""Instance used to send multiple commands on the same Powershell process.
113154
Will be instantiated on loading and automatically stopped.
114155
"""
115156
def __init__(self):
116-
if sys.version_info[0:2] < (3, 4): # Bug was fixed on python 3.4+
117-
# Fix https://bugs.python.org/issue19575
118-
# and https://github.com/secdev/scapy/issues/1136
119-
_suppress_file_handles_inheritance()
120-
# Start & redirect input
121-
if conf.prog.powershell:
122-
self.process = sp.Popen([conf.prog.powershell,
123-
"-NoLogo", "-NonInteractive", # Do not print headers
124-
"-Command", "-"], # Listen commands from stdin
125-
stdout=sp.PIPE,
126-
stdin=sp.PIPE,
127-
stderr=sp.STDOUT)
128-
self.cmd = False
129-
else: # Fallback on CMD (powershell-only commands will fail, but scapy use the VBS fallback)
130-
self.process = sp.Popen([conf.prog.cmd],
131-
stdout=sp.PIPE,
132-
stdin=sp.PIPE,
133-
stderr=sp.STDOUT)
134-
self.cmd = True
157+
opened_handles = _suppress_file_handles_inheritance()
158+
try:
159+
# Start & redirect input
160+
if conf.prog.powershell:
161+
cmd = [conf.prog.powershell,
162+
"-NoLogo", "-NonInteractive", # Do not print headers
163+
"-Command", "-"] # Listen commands from stdin
164+
else: # Fallback on CMD (powershell-only commands will fail, but scapy use the VBS fallback)
165+
cmd = [conf.prog.cmd]
166+
self.process = sp.Popen(cmd, stdout=sp.PIPE, stdin=sp.PIPE, stderr=sp.STDOUT)
167+
self.cmd = not conf.prog.powershell
168+
finally:
169+
_restore_file_handles_inheritance(opened_handles)
135170
self.buffer = []
136171
self.running = True
137172
self.query_complete = Event()

0 commit comments

Comments
 (0)