mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2025-01-24 00:04:23 +03:00
first attempt to have --os-pwn and other takeover switches work across Windows and Linux - issue #28
This commit is contained in:
parent
c44a829b9b
commit
510ceb6e19
|
@ -3309,3 +3309,21 @@ def isNumber(value):
|
|||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def pollProcess(process, suppress_errors=False):
|
||||
while True:
|
||||
dataToStdout(".")
|
||||
time.sleep(1)
|
||||
|
||||
returncode = process.poll()
|
||||
|
||||
if returncode is not None:
|
||||
if not suppress_errors:
|
||||
if returncode == 0:
|
||||
dataToStdout(" done\n")
|
||||
elif returncode < 0:
|
||||
dataToStdout(" process terminated by signal %d\n" % returncode)
|
||||
elif returncode > 0:
|
||||
dataToStdout(" quit unexpectedly with return code %d\n" % returncode)
|
||||
|
||||
break
|
||||
|
|
|
@ -7,13 +7,19 @@ See the file 'doc/COPYING' for copying permission
|
|||
|
||||
import errno
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
|
||||
from lib.core.common import dataToStdout
|
||||
from lib.core.settings import IS_WIN
|
||||
|
||||
if not IS_WIN:
|
||||
if IS_WIN:
|
||||
from win32file import ReadFile, WriteFile
|
||||
from win32pipe import PeekNamedPipe
|
||||
import msvcrt
|
||||
else:
|
||||
import select
|
||||
import fcntl
|
||||
|
||||
if (sys.hexversion >> 16) >= 0x202:
|
||||
|
@ -61,30 +67,131 @@ def blockingWriteToFD(fd, data):
|
|||
|
||||
break
|
||||
|
||||
def setNonBlocking(fd):
|
||||
"""
|
||||
Make a file descriptor non-blocking
|
||||
"""
|
||||
# the following code is taken from http://code.activestate.com/recipes/440554-module-to-allow-asynchronous-subprocess-use-on-win/
|
||||
class Popen(subprocess.Popen):
|
||||
def recv(self, maxsize=None):
|
||||
return self._recv('stdout', maxsize)
|
||||
|
||||
if IS_WIN is not True:
|
||||
flags = fcntl.fcntl(fd, FCNTL.F_GETFL)
|
||||
flags = flags | os.O_NONBLOCK
|
||||
fcntl.fcntl(fd, FCNTL.F_SETFL, flags)
|
||||
def recv_err(self, maxsize=None):
|
||||
return self._recv('stderr', maxsize)
|
||||
|
||||
def pollProcess(process, suppress_errors=False):
|
||||
while True:
|
||||
dataToStdout(".")
|
||||
time.sleep(1)
|
||||
def send_recv(self, input='', maxsize=None):
|
||||
return self.send(input), self.recv(maxsize), self.recv_err(maxsize)
|
||||
|
||||
returncode = process.poll()
|
||||
def get_conn_maxsize(self, which, maxsize):
|
||||
if maxsize is None:
|
||||
maxsize = 1024
|
||||
elif maxsize < 1:
|
||||
maxsize = 1
|
||||
return getattr(self, which), maxsize
|
||||
|
||||
if returncode is not None:
|
||||
if not suppress_errors:
|
||||
if returncode == 0:
|
||||
dataToStdout(" done\n")
|
||||
elif returncode < 0:
|
||||
dataToStdout(" process terminated by signal %d\n" % returncode)
|
||||
elif returncode > 0:
|
||||
dataToStdout(" quit unexpectedly with return code %d\n" % returncode)
|
||||
def _close(self, which):
|
||||
getattr(self, which).close()
|
||||
setattr(self, which, None)
|
||||
|
||||
if subprocess.mswindows:
|
||||
def send(self, input):
|
||||
if not self.stdin:
|
||||
return None
|
||||
|
||||
try:
|
||||
x = msvcrt.get_osfhandle(self.stdin.fileno())
|
||||
(errCode, written) = WriteFile(x, input)
|
||||
except ValueError:
|
||||
return self._close('stdin')
|
||||
except (subprocess.pywintypes.error, Exception), why:
|
||||
if why[0] in (109, errno.ESHUTDOWN):
|
||||
return self._close('stdin')
|
||||
raise
|
||||
|
||||
return written
|
||||
|
||||
def _recv(self, which, maxsize):
|
||||
conn, maxsize = self.get_conn_maxsize(which, maxsize)
|
||||
if conn is None:
|
||||
return None
|
||||
|
||||
try:
|
||||
x = msvcrt.get_osfhandle(conn.fileno())
|
||||
(read, nAvail, nMessage) = PeekNamedPipe(x, 0)
|
||||
if maxsize < nAvail:
|
||||
nAvail = maxsize
|
||||
if nAvail > 0:
|
||||
(errCode, read) = ReadFile(x, nAvail, None)
|
||||
except ValueError:
|
||||
return self._close(which)
|
||||
except (subprocess.pywintypes.error, Exception), why:
|
||||
if why[0] in (109, errno.ESHUTDOWN):
|
||||
return self._close(which)
|
||||
raise
|
||||
|
||||
if self.universal_newlines:
|
||||
read = self._translate_newlines(read)
|
||||
return read
|
||||
else:
|
||||
def send(self, input):
|
||||
if not self.stdin:
|
||||
return None
|
||||
|
||||
if not select.select([], [self.stdin], [], 0)[1]:
|
||||
return 0
|
||||
|
||||
try:
|
||||
written = os.write(self.stdin.fileno(), input)
|
||||
except OSError, why:
|
||||
if why[0] == errno.EPIPE: #broken pipe
|
||||
return self._close('stdin')
|
||||
raise
|
||||
|
||||
return written
|
||||
|
||||
def _recv(self, which, maxsize):
|
||||
conn, maxsize = self.get_conn_maxsize(which, maxsize)
|
||||
if conn is None:
|
||||
return None
|
||||
|
||||
flags = fcntl.fcntl(conn, fcntl.F_GETFL)
|
||||
if not conn.closed:
|
||||
fcntl.fcntl(conn, fcntl.F_SETFL, flags| os.O_NONBLOCK)
|
||||
|
||||
try:
|
||||
if not select.select([conn], [], [], 0)[0]:
|
||||
return ''
|
||||
|
||||
r = conn.read(maxsize)
|
||||
if not r:
|
||||
return self._close(which)
|
||||
|
||||
if self.universal_newlines:
|
||||
r = self._translate_newlines(r)
|
||||
return r
|
||||
finally:
|
||||
if not conn.closed:
|
||||
fcntl.fcntl(conn, fcntl.F_SETFL, flags)
|
||||
|
||||
def recv_some(p, t=.1, e=1, tr=5, stderr=0):
|
||||
if tr < 1:
|
||||
tr = 1
|
||||
x = time.time()+t
|
||||
y = []
|
||||
r = ''
|
||||
pr = p.recv
|
||||
if stderr:
|
||||
pr = p.recv_err
|
||||
while time.time() < x or r:
|
||||
r = pr()
|
||||
if r is None:
|
||||
break
|
||||
elif r:
|
||||
y.append(r)
|
||||
else:
|
||||
time.sleep(max((x-time.time())/tr, 0))
|
||||
return ''.join(y)
|
||||
|
||||
def send_all(p, data):
|
||||
if not data:
|
||||
return
|
||||
|
||||
while len(data):
|
||||
sent = p.send(data)
|
||||
data = buffer(data, sent)
|
||||
|
|
|
@ -13,13 +13,13 @@ from subprocess import PIPE
|
|||
from subprocess import Popen as execute
|
||||
|
||||
from lib.core.common import dataToStdout
|
||||
from lib.core.common import pollProcess
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import logger
|
||||
from lib.core.data import paths
|
||||
from lib.core.revision import getRevisionNumber
|
||||
from lib.core.settings import GIT_REPOSITORY
|
||||
from lib.core.settings import IS_WIN
|
||||
from lib.core.subprocessng import pollProcess
|
||||
|
||||
def update():
|
||||
if not conf.updateAll:
|
||||
|
|
|
@ -10,9 +10,7 @@ import re
|
|||
import sys
|
||||
import time
|
||||
|
||||
from select import select
|
||||
from subprocess import PIPE
|
||||
from subprocess import Popen as execute
|
||||
|
||||
from lib.core.common import dataToStdout
|
||||
from lib.core.common import Backend
|
||||
|
@ -21,6 +19,7 @@ from lib.core.common import getRemoteIP
|
|||
from lib.core.common import getUnicode
|
||||
from lib.core.common import normalizePath
|
||||
from lib.core.common import ntToPosixSlashes
|
||||
from lib.core.common import pollProcess
|
||||
from lib.core.common import randomRange
|
||||
from lib.core.common import randomStr
|
||||
from lib.core.common import readInput
|
||||
|
@ -35,9 +34,14 @@ from lib.core.settings import IS_WIN
|
|||
from lib.core.settings import UNICODE_ENCODING
|
||||
from lib.core.subprocessng import blockingReadFromFD
|
||||
from lib.core.subprocessng import blockingWriteToFD
|
||||
from lib.core.subprocessng import pollProcess
|
||||
from lib.core.subprocessng import setNonBlocking
|
||||
from lib.core.subprocessng import Popen as execute
|
||||
from lib.core.subprocessng import send_all
|
||||
from lib.core.subprocessng import recv_some
|
||||
|
||||
if IS_WIN:
|
||||
import msvcrt
|
||||
else:
|
||||
from select import select
|
||||
|
||||
class Metasploit:
|
||||
"""
|
||||
|
@ -410,14 +414,14 @@ class Metasploit:
|
|||
if not Backend.isOs(OS.WINDOWS):
|
||||
return
|
||||
|
||||
proc.stdin.write("use espia\n")
|
||||
proc.stdin.write("use incognito\n")
|
||||
send_all(proc, "use espia\n")
|
||||
send_all(proc, "use incognito\n")
|
||||
# This extension is loaded by default since Metasploit > 3.7
|
||||
#proc.stdin.write("use priv\n")
|
||||
#send_all(proc, "use priv\n")
|
||||
# This extension freezes the connection on 64-bit systems
|
||||
#proc.stdin.write("use sniffer\n")
|
||||
proc.stdin.write("sysinfo\n")
|
||||
proc.stdin.write("getuid\n")
|
||||
#send_all(proc, "use sniffer\n")
|
||||
send_all(proc, "sysinfo\n")
|
||||
send_all(proc, "getuid\n")
|
||||
|
||||
if conf.privEsc:
|
||||
print
|
||||
|
@ -427,7 +431,7 @@ class Metasploit:
|
|||
infoMsg += "techniques, including kitrap0d"
|
||||
logger.info(infoMsg)
|
||||
|
||||
proc.stdin.write("getsystem\n")
|
||||
send_all(proc, "getsystem\n")
|
||||
|
||||
infoMsg = "displaying the list of Access Tokens availables. "
|
||||
infoMsg += "Choose which user you want to impersonate by "
|
||||
|
@ -435,15 +439,11 @@ class Metasploit:
|
|||
infoMsg += "'getsystem' does not success to elevate privileges"
|
||||
logger.info(infoMsg)
|
||||
|
||||
proc.stdin.write("list_tokens -u\n")
|
||||
proc.stdin.write("getuid\n")
|
||||
send_all(proc, "list_tokens -u\n")
|
||||
send_all(proc, "getuid\n")
|
||||
|
||||
def _controlMsfCmd(self, proc, func):
|
||||
stdin_fd = sys.stdin.fileno()
|
||||
setNonBlocking(stdin_fd)
|
||||
|
||||
proc_out_fd = proc.stdout.fileno()
|
||||
setNonBlocking(proc_out_fd)
|
||||
|
||||
while True:
|
||||
returncode = proc.poll()
|
||||
|
@ -456,39 +456,63 @@ class Metasploit:
|
|||
return returncode
|
||||
|
||||
try:
|
||||
ready_fds = select([stdin_fd, proc_out_fd], [], [], 1)
|
||||
if IS_WIN:
|
||||
timeout = 3
|
||||
|
||||
if stdin_fd in ready_fds[0]:
|
||||
try:
|
||||
proc.stdin.write(blockingReadFromFD(stdin_fd))
|
||||
except IOError:
|
||||
# Probably the child has exited
|
||||
pass
|
||||
inp = ""
|
||||
start_time = time.time()
|
||||
|
||||
if proc_out_fd in ready_fds[0]:
|
||||
out = blockingReadFromFD(proc_out_fd)
|
||||
blockingWriteToFD(sys.stdout.fileno(), out)
|
||||
while True:
|
||||
if msvcrt.kbhit():
|
||||
char = msvcrt.getche()
|
||||
|
||||
# For --os-pwn and --os-bof
|
||||
pwnBofCond = self.connectionStr.startswith("reverse")
|
||||
pwnBofCond &= "Starting the payload handler" in out
|
||||
if ord(char) == 13: # enter_key
|
||||
break
|
||||
elif ord(char) >= 32: # space_char
|
||||
inp += char
|
||||
|
||||
# For --os-smbrelay
|
||||
smbRelayCond = "Server started" in out
|
||||
if len(inp) == 0 and (time.time() - start_time) > timeout:
|
||||
break
|
||||
|
||||
if pwnBofCond or smbRelayCond:
|
||||
func()
|
||||
if len(inp) > 0:
|
||||
try:
|
||||
send_all(proc, inp)
|
||||
except IOError:
|
||||
# Probably the child has exited
|
||||
pass
|
||||
else:
|
||||
ready_fds = select([stdin_fd], [], [], 1)
|
||||
|
||||
if "Starting the payload handler" in out and "shell" in self.payloadStr:
|
||||
if Backend.isOs(OS.WINDOWS):
|
||||
proc.stdin.write("whoami\n")
|
||||
else:
|
||||
proc.stdin.write("uname -a ; id\n")
|
||||
if stdin_fd in ready_fds[0]:
|
||||
try:
|
||||
send_all(proc, blockingReadFromFD(stdin_fd))
|
||||
except IOError:
|
||||
# Probably the child has exited
|
||||
pass
|
||||
|
||||
metSess = re.search("Meterpreter session ([\d]+) opened", out)
|
||||
out = recv_some(proc, t=.1, e=0)
|
||||
blockingWriteToFD(sys.stdout.fileno(), out)
|
||||
|
||||
if metSess:
|
||||
self._loadMetExtensions(proc, metSess.group(1))
|
||||
# For --os-pwn and --os-bof
|
||||
pwnBofCond = self.connectionStr.startswith("reverse")
|
||||
pwnBofCond &= "Starting the payload handler" in out
|
||||
|
||||
# For --os-smbrelay
|
||||
smbRelayCond = "Server started" in out
|
||||
|
||||
if pwnBofCond or smbRelayCond:
|
||||
func()
|
||||
|
||||
if "Starting the payload handler" in out and "shell" in self.payloadStr:
|
||||
if Backend.isOs(OS.WINDOWS):
|
||||
send_all(proc, "whoami\n")
|
||||
else:
|
||||
send_all(proc, "uname -a ; id\n")
|
||||
|
||||
metSess = re.search("Meterpreter session ([\d]+) opened", out)
|
||||
|
||||
if metSess:
|
||||
self._loadMetExtensions(proc, metSess.group(1))
|
||||
|
||||
except EOFError:
|
||||
returncode = proc.wait()
|
||||
|
|
Loading…
Reference in New Issue
Block a user