| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -23,7 +23,9 @@ | |||
| 23 | 23 | import string | |
| 24 | 24 | import struct | |
| 25 | 25 | import sys | |
| 26 | + import tempfile | ||
| 26 | 27 | import time | |
| 28 | + import types | ||
| 27 | 29 | import urlparse | |
| 28 | 30 | import unicodedata | |
| 29 | 31 | ||
@@ -205,31 +207,86 @@ def __init__(self): | |||
| 205 | 207 | self.chunks = [[]] | |
| 206 | 208 | self.cache = None | |
| 207 | 209 | self.length = 0 | |
| 210 | + self.filenames = set() | ||
| 208 | 211 | ||
| 209 | 212 | def append(self, value): | |
| 210 | 213 | self.chunks[-1].append(value) | |
| 211 | 214 | if len(self.chunks[-1]) >= BIGARRAY_CHUNK_LENGTH: | |
| 212 | - fp = tempfile.TemporaryFile() | ||
| 213 | - pickle.dump(self.chunks[-1], fp) | ||
| 215 | + filename = self._dump(self.chunks[-1]) | ||
| 214 | 216 | del(self.chunks[-1][:]) | |
| 215 | - self.chunks[-1] = fp | ||
| 217 | + self.chunks[-1] = filename | ||
| 216 | 218 | self.chunks.append([]) | |
| 217 | 219 | ||
| 220 | + def pop(self): | ||
| 221 | + if len(self.chunks[-1]) < 1: | ||
| 222 | + self.chunks.pop() | ||
| 223 | + fp = open(self.chunks[-1], 'rb') | ||
| 224 | + self.chunks[-1] = pickle.load(fp) | ||
| 225 | + fp.close() | ||
| 226 | + return self.chunks[-1].pop() | ||
| 227 | + | ||
| 228 | + def index(self, value): | ||
| 229 | + for index in xrange(len(self)): | ||
| 230 | + if self[index] == value: | ||
| 231 | + return index | ||
| 232 | + return ValueError, "%s is not in list" % value | ||
| 233 | + | ||
| 234 | + def _dump(self, value): | ||
| 235 | + handle, filename = tempfile.mkstemp() | ||
| 236 | + self.filenames.add(filename) | ||
| 237 | + os.close(handle) | ||
| 238 | + fp = open(filename, 'w+b') | ||
| 239 | + pickle.dump(value, fp) | ||
| 240 | + fp.close() | ||
| 241 | + return filename | ||
| 242 | + | ||
| 243 | + def _checkcache(self, index): | ||
| 244 | + if (self.cache and self.cache[0] != index and self.cache[2]): | ||
| 245 | + filename = self._dump(self.cache[1]) | ||
| 246 | + self.chunks[self.cache[0]] = filename | ||
| 247 | + if not (self.cache and self.cache[0] == index): | ||
| 248 | + fp = open(self.chunks[index], 'rb') | ||
| 249 | + self.cache = [index, pickle.load(fp), False] | ||
| 250 | + fp.close() | ||
| 251 | + | ||
| 218 | 252 | def __getitem__(self, y): | |
| 219 | 253 | index = y / BIGARRAY_CHUNK_LENGTH | |
| 220 | 254 | offset = y % BIGARRAY_CHUNK_LENGTH | |
| 221 | 255 | chunk = self.chunks[index] | |
| 222 | 256 | if isinstance(chunk, list): | |
| 223 | 257 | return chunk[offset] | |
| 224 | 258 | else: | |
| 225 | - if not (self.cache and self.cache[0] == index): | ||
| 226 | - chunk.seek(0) | ||
| 227 | - self.cache = (index, pickle.load(chunk)) | ||
| 259 | + self._checkcache(index) | ||
| 228 | 260 | return self.cache[1][offset] | |
| 229 | 261 | ||
| 262 | + def __setitem__(self, y, value): | ||
| 263 | + index = y / BIGARRAY_CHUNK_LENGTH | ||
| 264 | + offset = y % BIGARRAY_CHUNK_LENGTH | ||
| 265 | + chunk = self.chunks[index] | ||
| 266 | + if isinstance(chunk, list): | ||
| 267 | + chunk[offset] = value | ||
| 268 | + else: | ||
| 269 | + self._checkcache(index) | ||
| 270 | + self.cache[1][offset] = value | ||
| 271 | + self.cache[2] = True # dirty flag | ||
| 272 | + | ||
| 273 | + def __repr__(self): | ||
| 274 | + return "%s%s" % ("..." if len(self.chunks) > 1 else "", self.chunks[-1].__repr__()) | ||
| 275 | + | ||
| 276 | + def __iter__(self): | ||
| 277 | + for i in xrange(len(self)): | ||
| 278 | + yield self[i] | ||
| 279 | + | ||
| 230 | 280 | def __len__(self): | |
| 231 | 281 | return len(self.chunks[-1]) if len(self.chunks) == 1 else (len(self.chunks) - 1) * BIGARRAY_CHUNK_LENGTH + len(self.chunks[-1]) | |
| 232 | 282 | ||
| 283 | + def __del__(self): | ||
| 284 | + for filename in self.filenames: | ||
| 285 | + try: | ||
| 286 | + os.remove(filename) | ||
| 287 | + except OSError: | ||
| 288 | + pass | ||
| 289 | + | ||
| 233 | 290 | class DynamicContentItem: | |
| 234 | 291 | """ | |
| 235 | 292 | Represents line in content page with dynamic properties (candidate | |
@@ -561,6 +618,15 @@ def isVersionGreaterOrEqualThan(version): | |||
| 561 | 618 | def isOs(os): | |
| 562 | 619 | return Backend.getOs() is not None and Backend.getOs().lower() == os.lower() | |
| 563 | 620 | ||
| 621 | + # Reference: http://code.activestate.com/recipes/325205-cache-decorator-in-python-24/ | ||
| 622 | + def cachedmethod(f, cache={}): | ||
| 623 | + def g(*args, **kwargs): | ||
| 624 | + key = ( f, tuple(args), frozenset(kwargs.items()) ) | ||
| 625 | + if key not in cache: | ||
| 626 | + cache[key] = f(*args, **kwargs) | ||
| 627 | + return cache[key] | ||
| 628 | + return g | ||
| 629 | + | ||
| 564 | 630 | def paramToDict(place, parameters=None): | |
| 565 | 631 | """ | |
| 566 | 632 | Split the parameters into names and values, check if these parameters | |
@@ -1266,7 +1332,7 @@ def parseUnionPage(output, expression, partial=False, condition=None, sort=True) | |||
| 1266 | 1332 | if output is None: | |
| 1267 | 1333 | return None | |
| 1268 | 1334 | ||
| 1269 | - data = [] | ||
| 1335 | + data = BigArray() | ||
| 1270 | 1336 | ||
| 1271 | 1337 | outCond1 = ( output.startswith(kb.misc.start) and output.endswith(kb.misc.stop) ) | |
| 1272 | 1338 | outCond2 = ( output.startswith(DUMP_START_MARKER) and output.endswith(DUMP_STOP_MARKER) ) | |
@@ -2204,6 +2270,7 @@ def isNumPosStrValue(value): | |||
| 2204 | 2270 | ||
| 2205 | 2271 | return value and isinstance(value, basestring) and value.isdigit() and value != "0" | |
| 2206 | 2272 | ||
| 2273 | + @cachedmethod | ||
| 2207 | 2274 | def aliasToDbmsEnum(dbms): | |
| 2208 | 2275 | """ | |
| 2209 | 2276 | Returns major DBMS name from a given alias | |
@@ -2730,8 +2797,8 @@ def isNoneValue(value): | |||
| 2730 | 2797 | if len(value) == 1: | |
| 2731 | 2798 | return isNoneValue(value[0]) | |
| 2732 | 2799 | else: | |
| 2733 | - for i in xrange(len(value)): | ||
| 2734 | - if value[i] and value[i] != "None": | ||
| 2800 | + for item in value: | ||
| 2801 | + if item and item != "None": | ||
| 2735 | 2802 | return False | |
| 2736 | 2803 | return True | |
| 2737 | 2804 | elif isinstance(value, dict): | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -24,6 +24,7 @@ | |||
| 24 | 24 | from lib.core.data import logger | |
| 25 | 25 | from lib.core.enums import DBMS | |
| 26 | 26 | from lib.core.replication import Replication | |
| 27 | + from lib.core.settings import TRIM_STDOUT_DUMP_SIZE | ||
| 27 | 28 | from lib.core.settings import UNICODE_ENCODING | |
| 28 | 29 | ||
| 29 | 30 | class Dump: | |
@@ -37,9 +38,10 @@ def __init__(self): | |||
| 37 | 38 | self.__outputFile = None | |
| 38 | 39 | self.__outputFP = None | |
| 39 | 40 | ||
| 40 | - def __write(self, data, n=True): | ||
| 41 | + def __write(self, data, n=True, console=True): | ||
| 41 | 42 | text = "%s%s" % (data, "\n" if n else " ") | |
| 42 | - dataToStdout(text) | ||
| 43 | + if console: | ||
| 44 | + dataToStdout(text) | ||
| 43 | 45 | ||
| 44 | 46 | self.__outputFP.write(text) | |
| 45 | 47 | self.__outputFP.flush() | |
@@ -407,7 +409,13 @@ def dbTableValues(self, tableValues): | |||
| 407 | 409 | if conf.replicate: | |
| 408 | 410 | rtable.beginTransaction() | |
| 409 | 411 | ||
| 412 | + if count > TRIM_STDOUT_DUMP_SIZE: | ||
| 413 | + warnMsg = "console output will be trimmed " | ||
| 414 | + warnMsg += "due to the large table size" | ||
| 415 | + logger.warning(warnMsg) | ||
| 416 | + | ||
| 410 | 417 | for i in range(count): | |
| 418 | + console = (i >= count - TRIM_STDOUT_DUMP_SIZE) | ||
| 411 | 419 | field = 1 | |
| 412 | 420 | values = [] | |
| 413 | 421 | ||
@@ -429,7 +437,7 @@ def dbTableValues(self, tableValues): | |||
| 429 | 437 | values.append(value) | |
| 430 | 438 | maxlength = int(info["length"]) | |
| 431 | 439 | blank = " " * (maxlength - len(value)) | |
| 432 | - self.__write("| %s%s" % (value, blank), n=False) | ||
| 440 | + self.__write("| %s%s" % (value, blank), n=False, console=console) | ||
| 433 | 441 | ||
| 434 | 442 | if not conf.replicate: | |
| 435 | 443 | if not conf.multipleTargets and field == fields: | |
@@ -442,7 +450,7 @@ def dbTableValues(self, tableValues): | |||
| 442 | 450 | if conf.replicate: | |
| 443 | 451 | rtable.insert(values) | |
| 444 | 452 | ||
| 445 | - self.__write("|") | ||
| 453 | + self.__write("|", console=console) | ||
| 446 | 454 | ||
| 447 | 455 | if not conf.multipleTargets and not conf.replicate: | |
| 448 | 456 | dataToDumpFile(dumpFP, "\n") | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -31,7 +31,7 @@ def profile(profileOutputFile=None, dotOutputFile=None, imageOutputFile=None): | |||
| 31 | 31 | errMsg = "profiling requires third-party libraries (%s). " % getUnicode(e, UNICODE_ENCODING) | |
| 32 | 32 | errMsg += "Quick steps:%s" % os.linesep | |
| 33 | 33 | errMsg += "1) Install http://code.google.com/p/pydot/%s" % os.linesep | |
| 34 | - errMsg += "2) sudo apt-get install python-profiler graphviz" | ||
| 34 | + errMsg += "2) sudo apt-get install python-pyparsing python-profiler graphviz" | ||
| 35 | 35 | logger.error(errMsg) | |
| 36 | 36 | ||
| 37 | 37 | return | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -383,5 +383,8 @@ | |||
| 383 | 383 | # Used for status representation in dictionary attack phase | |
| 384 | 384 | ROTATING_CHARS = ('\\', '|', '|', '/', '-') | |
| 385 | 385 | ||
| 386 | - # Chunk length used in BigArray object (only last one is held in memory) | ||
| 387 | - BIGARRAY_CHUNK_LENGTH = 10000 | ||
| 386 | + # Chunk length (in items) used by BigArray objects (only last chunk and cached one are held in memory) | ||
| 387 | + BIGARRAY_CHUNK_LENGTH = 5000 | ||
| 388 | + | ||
| 389 | + # Only console display last n table rows | ||
| 390 | + TRIM_STDOUT_DUMP_SIZE = 256 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -12,6 +12,7 @@ | |||
| 12 | 12 | ||
| 13 | 13 | from lib.core.agent import agent | |
| 14 | 14 | from lib.core.common import Backend | |
| 15 | + from lib.core.common import BigArray | ||
| 15 | 16 | from lib.core.common import calculateDeltaSeconds | |
| 16 | 17 | from lib.core.common import cleanQuery | |
| 17 | 18 | from lib.core.common import dataToSessionFile | |
@@ -123,7 +124,7 @@ def __goInferenceProxy(expression, fromUser=False, expected=None, batch=False, r | |||
| 123 | 124 | count = None | |
| 124 | 125 | startLimit = 0 | |
| 125 | 126 | stopLimit = None | |
| 126 | - outputs = [] | ||
| 127 | + outputs = BigArray() | ||
| 127 | 128 | test = None | |
| 128 | 129 | untilLimitChar = None | |
| 129 | 130 | untilOrderChar = None | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -13,6 +13,7 @@ | |||
| 13 | 13 | ||
| 14 | 14 | from lib.core.agent import agent | |
| 15 | 15 | from lib.core.common import Backend | |
| 16 | + from lib.core.common import BigArray | ||
| 16 | 17 | from lib.core.common import calculateDeltaSeconds | |
| 17 | 18 | from lib.core.common import dataToSessionFile | |
| 18 | 19 | from lib.core.common import dataToStdout | |
@@ -321,7 +322,7 @@ def errorUse(expression, expected=None, resumeValue=True, dump=False): | |||
| 321 | 322 | threadData = getCurrentThreadData() | |
| 322 | 323 | threadData.shared.limits = range(startLimit, stopLimit) | |
| 323 | 324 | numThreads = min(conf.threads, len(threadData.shared.limits)) | |
| 324 | - threadData.shared.outputs = [] | ||
| 325 | + threadData.shared.outputs = BigArray() | ||
| 325 | 326 | ||
| 326 | 327 | if stopLimit > TURN_OFF_RESUME_INFO_LIMIT: | |
| 327 | 328 | kb.suppressResumeInfo = True | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -33,13 +33,12 @@ | |||
| 33 | 33 | ||
| 34 | 34 | from extra.pydes.pyDes import des | |
| 35 | 35 | from extra.pydes.pyDes import CBC | |
| 36 | + from lib.core.common import Backend | ||
| 36 | 37 | from lib.core.common import checkFile | |
| 37 | 38 | from lib.core.common import clearConsoleLine | |
| 38 | 39 | from lib.core.common import dataToStdout | |
| 39 | 40 | from lib.core.common import getCompiledRegex | |
| 40 | 41 | from lib.core.common import getFileItems | |
| 41 | - from lib.core.common import Backend | ||
| 42 | - from lib.core.common import getCompiledRegex | ||
| 43 | 42 | from lib.core.common import getPublicTypeMembers | |
| 44 | 43 | from lib.core.common import normalizeUnicode | |
| 45 | 44 | from lib.core.common import paths | |
@@ -252,6 +251,8 @@ def attackCachedUsersPasswords(): | |||
| 252 | 251 | kb.data.cachedUsersPasswords[user][i] += "%s clear-text password: %s" % ('\n' if kb.data.cachedUsersPasswords[user][i][-1] != '\n' else '', password) | |
| 253 | 252 | ||
| 254 | 253 | def attackDumpedTable(): | |
| 254 | + isOracle, isMySQL = Backend.isDbms(DBMS.ORACLE), Backend.isDbms(DBMS.MYSQL) | ||
| 255 | + | ||
| 255 | 256 | if kb.data.dumpedTable: | |
| 256 | 257 | table = kb.data.dumpedTable | |
| 257 | 258 | columns = table.keys() | |
@@ -275,7 +276,7 @@ def attackDumpedTable(): | |||
| 275 | 276 | ||
| 276 | 277 | value = table[column]['values'][i] | |
| 277 | 278 | ||
| 278 | - if hashRecognition(value): | ||
| 279 | + if hashRecognition(value, isOracle, isMySQL): | ||
| 279 | 280 | if colUser: | |
| 280 | 281 | if table[colUser]['values'][i] not in attack_dict: | |
| 281 | 282 | attack_dict[table[colUser]['values'][i]] = [] | |
@@ -310,15 +311,15 @@ def attackDumpedTable(): | |||
| 310 | 311 | table[column]['values'][i] += " (%s)" % password | |
| 311 | 312 | table[column]['length'] = max(table[column]['length'], len(table[column]['values'][i])) | |
| 312 | 313 | ||
| 313 | - def hashRecognition(value): | ||
| 314 | + def hashRecognition(value, isOracle=False, isMySQL=False): | ||
| 314 | 315 | retVal = None | |
| 315 | 316 | ||
| 316 | 317 | if isinstance(value, basestring): | |
| 317 | 318 | for name, regex in getPublicTypeMembers(HASH): | |
| 318 | 319 | # Hashes for Oracle and old MySQL look the same hence these checks | |
| 319 | - if Backend.isDbms(DBMS.ORACLE) and regex == HASH.MYSQL_OLD: | ||
| 320 | + if isOracle and regex == HASH.MYSQL_OLD: | ||
| 320 | 321 | continue | |
| 321 | - elif Backend.isDbms(DBMS.MYSQL) and regex == HASH.ORACLE_OLD: | ||
| 322 | + elif isMySQL and regex == HASH.ORACLE_OLD: | ||
| 322 | 323 | continue | |
| 323 | 324 | elif regex == HASH.CRYPT_GENERIC: | |
| 324 | 325 | if any([getCompiledRegex(GENERAL_IP_ADDRESS_REGEX).match(value), value.lower() == value, value.upper() == value, value.isdigit()]): | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -13,6 +13,7 @@ | |||
| 13 | 13 | from lib.core.agent import agent | |
| 14 | 14 | from lib.core.common import arrayizeValue | |
| 15 | 15 | from lib.core.common import Backend | |
| 16 | + from lib.core.common import BigArray | ||
| 16 | 17 | from lib.core.common import clearConsoleLine | |
| 17 | 18 | from lib.core.common import dataToStdout | |
| 18 | 19 | from lib.core.common import getRange | |
@@ -1385,7 +1386,7 @@ def __pivotDumpTable(self, table, colList, count=None, blind=True): | |||
| 1385 | 1386 | ||
| 1386 | 1387 | for column in colList: | |
| 1387 | 1388 | lengths[column] = 0 | |
| 1388 | - entries[column] = [] | ||
| 1389 | + entries[column] = BigArray() | ||
| 1389 | 1390 | ||
| 1390 | 1391 | colList = sorted(colList, key=lambda x: len(x) if x else MAX_INT) | |
| 1391 | 1392 | ||
@@ -1706,7 +1707,7 @@ def dumpTable(self, foundData=None): | |||
| 1706 | 1707 | lengths[column] = 0 | |
| 1707 | 1708 | ||
| 1708 | 1709 | if column not in entries: | |
| 1709 | - entries[column] = [] | ||
| 1710 | + entries[column] = BigArray() | ||
| 1710 | 1711 | ||
| 1711 | 1712 | if Backend.getIdentifiedDbms() in ( DBMS.MYSQL, DBMS.PGSQL ): | |
| 1712 | 1713 | query = rootQuery.blind.query % (column, conf.db, conf.tbl, index) | |
| Back | FazBrowse Home | New Git URL |
0 commit comments