|
12 | 12 | import os, re, sys, socket, time, itertools, platform |
13 | 13 | import subprocess as sp |
14 | 14 | from glob import glob |
15 | | -import ctypes, tempfile |
| 15 | +import ctypes |
| 16 | +from ctypes import wintypes |
| 17 | +import tempfile |
16 | 18 | from threading import Thread, Event |
17 | 19 |
|
18 | 20 | import scapy |
|
27 | 29 | from scapy.modules.six.moves import range, zip, input, winreg |
28 | 30 | from scapy.compat import plain_str |
29 | 31 |
|
| 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 | + |
30 | 44 | conf.use_pcap = False |
31 | 45 | conf.use_dnet = False |
32 | 46 | conf.use_winpcapy = True |
@@ -80,58 +94,79 @@ def _windows_title(title=None): |
80 | 94 | """Updates the terminal title with the default one or with `title` |
81 | 95 | if provided.""" |
82 | 96 | 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)) |
85 | 98 |
|
86 | | -def _suppress_file_handles_inheritance(r=100): |
| 99 | +def _suppress_file_handles_inheritance(r=1000): |
87 | 100 | """HACK: python 2.7 file descriptors. |
88 | 101 |
|
89 | 102 | This magic hack fixes https://bugs.python.org/issue19575 |
| 103 | + and https://github.com/secdev/scapy/issues/1136 |
90 | 104 | by suppressing the HANDLE_FLAG_INHERIT flag to a range of |
91 | 105 | already opened file descriptors. |
| 106 | + Bug was fixed on python 3.4+ |
92 | 107 | """ |
93 | | - # See https://github.com/secdev/scapy/issues/1136 |
| 108 | + if sys.version_info[0:2] >= (3, 4): |
| 109 | + return [] |
| 110 | + |
94 | 111 | import stat |
95 | | - from ctypes import windll, wintypes |
96 | 112 | from msvcrt import get_osfhandle |
97 | 113 |
|
98 | 114 | HANDLE_FLAG_INHERIT = 0x00000001 |
99 | 115 |
|
| 116 | + handles = [] |
100 | 117 | for fd in range(r): |
101 | 118 | try: |
102 | 119 | s = os.fstat(fd) |
103 | 120 | except OSError: |
104 | 121 | continue |
105 | 122 | 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 |
110 | 151 |
|
111 | 152 | class _PowershellManager(Thread): |
112 | 153 | """Instance used to send multiple commands on the same Powershell process. |
113 | 154 | Will be instantiated on loading and automatically stopped. |
114 | 155 | """ |
115 | 156 | 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) |
135 | 170 | self.buffer = [] |
136 | 171 | self.running = True |
137 | 172 | self.query_complete = Event() |
|
0 commit comments