main_attack.py 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. """
  2. This module starts the probe response attack UI.
  3. Use --help to show possible parameters
  4. """
  5. import cmd
  6. import sys
  7. import argparse
  8. import logging
  9. import os
  10. import inspect
  11. import netifaces
  12. import time
  13. from report_fetcher import ReportFetcher
  14. from attack_logic import ProbeResponseAttackLogic
  15. is_simulation = True
  16. # Logging config
  17. logging.basicConfig(format="%(levelname)s (%(funcName)s): %(message)s")
  18. logger = logging.getLogger("pra_framework")
  19. logger.setLevel(logging.DEBUG)
  20. # TODO: change for testing
  21. if not is_simulation:
  22. dirname_save = time.strftime("attack_%Y_%m_%d__%H_%M_%S") + "/"
  23. else:
  24. dirname_save = "output_dir_testing" + "/"
  25. if not os.path.exists(dirname_save):
  26. logging.debug("creating new directory to save results: %s" % dirname_save)
  27. try:
  28. os.mkdir(dirname_save)
  29. except Exception as ex_createdir:
  30. print(ex_createdir)
  31. # Log to file, logging to console is already enabled
  32. fileHandler = logging.FileHandler(dirname_save + "/framework.log")
  33. logFormatter = logging.Formatter("%(asctime)s %(levelname)s (%(funcName)s): %(message)s",
  34. datefmt="%d/%m/%Y %I:%M:%S")
  35. fileHandler.setFormatter(logFormatter)
  36. logger.addHandler(fileHandler)
  37. class AttackUI(cmd.Cmd):
  38. """
  39. Command line UI to control the attack framework.
  40. """
  41. intro = """\n
  42. ____ ____ _____ ____ _ ____ _____
  43. | _ \| _ \| ____| _ \ / \ | _ \| ____|
  44. | |_) | |_) | _| | |_) / _ \ | |_) | _|
  45. | __/| _ <| |___| __/ ___ \| _ <| |___
  46. |_| |_| \_\_____|_| /_/ \_\_| \_\_____|
  47. ###########################################################
  48. # Welcome to PREPARE, the Probe REsPonse Attack fRamEwork #
  49. ###########################################################
  50. Type 'help' for available commands. Use tab for auto-completion.
  51. """
  52. promt = ">"
  53. file = None
  54. def __init__(self, parameters):
  55. super().__init__()
  56. try:
  57. mac_iface = netifaces.ifaddresses(parameters.interface)[17][0]["addr"]
  58. ip_for_iface = netifaces.ifaddresses(parameters.interface)[2][0]["addr"]
  59. self.attacklogic = ProbeResponseAttackLogic(interface_name=parameters.interface,
  60. ip_src=ip_for_iface,
  61. mac_source=mac_iface,
  62. mac_gw=parameters.macgw,
  63. rate_kbit_per_s=parameters.rate,
  64. marker_encoding=parameters.encoding,
  65. markerbits_value=parameters.markervaluebits,
  66. markerbits_checksum=parameters.checksumbits,
  67. rate=parameters.rate,
  68. base_dir_save=dirname_save,
  69. base_dir_zmap="../zmap",
  70. report_fetcher_classname=parameters.reportfetcherclass,
  71. use_feedback_ips=parameters.usefeedbackips,
  72. use_plus1=parameters.useplus1,
  73. is_simulation=is_simulation,
  74. _ip_stage1="0.0.0.0",
  75. _cidr_bits_stage1=0)
  76. except Exception as ex:
  77. raise FileExistsError("could not initialize logic: %r" % ex)
  78. def do_start(self, _):
  79. """
  80. Start the probe response attack
  81. """
  82. logging.info("starting attack")
  83. try:
  84. self.attacklogic.start()
  85. except Exception as ex:
  86. print(ex)
  87. def do_stop(self, _):
  88. """
  89. Stop the probe response attack
  90. """
  91. logging.info("stopping attack")
  92. self.attacklogic.stop()
  93. def do_setreportfetcher(self, _):
  94. """
  95. Set a new reportfetcher to fetch report events of the attacked CIDS.
  96. """
  97. def check(clz_search):
  98. return inspect.isclass(clz_search) and issubclass(clz_search, ReportFetcher) and clz_search != ReportFetcher
  99. classes = inspect.getmembers(sys.modules["report_fetcher"], check)
  100. print("available classes (chose 0-%d):" % (len(classes) - 1))
  101. for cnt, clz in enumerate(classes):
  102. print("%d: %s" % (cnt, clz[1].__name__))
  103. try:
  104. index = int(input("\nNew report fetcher class: "))
  105. self.attacklogic.set_report_fetcher_class(classes[index][0])
  106. except:
  107. print("did not understand, won't change anything")
  108. def do_setrate(self, rate):
  109. """
  110. Change the probe rate of the scanner (Kbit/s)
  111. """
  112. try:
  113. rate = int(rate)
  114. logger.info("New attack rate: %d Kbit/s" % rate)
  115. self.attacklogic.rate_kbit_per_s = rate
  116. except:
  117. print("did not understand, won't change anything")
  118. def do_setverbosity(self, _):
  119. """
  120. Change the frameworks log verbosity (0=WARNING, 1=INFO, 2=DEBUG)
  121. """
  122. try:
  123. level = int(input("\nNew log level 0-2:"))
  124. levels = [logging.WARNING, logging.INFO, logging.DEBUG]
  125. logger.setLevel(levels[level])
  126. except:
  127. print("did not understand, won't change anything")
  128. def do_stats(self, _):
  129. """
  130. Show basic statistics about the attack.
  131. """
  132. logging.info("Showing statistics:")
  133. logger.info("Attack durations, groups, addresses (1st = root, last = identified):")
  134. seconds_total = 0
  135. identified_group_index = 0
  136. try:
  137. for groupstore in self.attacklogic.iterations:
  138. start = groupstore[0][0]
  139. end = groupstore[0][1]
  140. diff = 0 if end == 0 else (end - start)
  141. seconds_total += diff
  142. groups = groupstore[2]
  143. addresses = groupstore[3]
  144. identified_groups = 0
  145. identified_addr = 0
  146. if identified_group_index > 0:
  147. try:
  148. # group store 2 (iteration) = group handler iteration 1
  149. identified_groups = sum([1 for gti in self.attacklogic.grouphandler.identified_groups
  150. if gti[2] == identified_group_index])
  151. identified_addr = sum([gti[0].amount_addresses for gti in self.attacklogic.grouphandler.identified_groups
  152. if gti[2] == identified_group_index])
  153. except:
  154. pass
  155. identified_group_index += 1
  156. logger.info("%d -> %d (diff: %d), groups: %d, addresses: %d, identified g: %d, identified a: %d" %
  157. (start, end, diff, groups, addresses, identified_groups, identified_addr))
  158. logger.info("seconds total: %d" % seconds_total)
  159. logger.info("probes total: [first iteration] + %d" % self.attacklogic.get_amount_of_probes())
  160. logger.info("identified groups: %d" % len(self.attacklogic.grouphandler.identified_groups))
  161. logger.info("identified addresses: %d" %
  162. sum([gti[0].amount_addresses for gti in self.attacklogic.grouphandler.identified_groups]))
  163. except Exception as ex:
  164. logger.warning("try again on less activity")
  165. logger.warning(ex)
  166. def do_quit(self, _):
  167. """
  168. Shutdown the attack framework.
  169. """
  170. sys.exit(0)
  171. if __name__ == "__main__":
  172. parser = argparse.ArgumentParser()
  173. parser.add_argument("-i", "--interface", help="Interface to send on packets",
  174. required=True)
  175. parser.add_argument("-m", "--macgw", help="MAC address of gateway",
  176. required=True)
  177. parser.add_argument("-r", "--rate", type=int, help="Rate used to send packets (Kbit/s)",
  178. default=1000)
  179. parser.add_argument("-e", "--encoding", type=int, help="Encoding to be used. Single or bit-OR combination (1=dst port,"
  180. "2=src IP, 4=src port)",
  181. default=5)
  182. # WARNING: setting marker values too low will make the attack impossible
  183. parser.add_argument("-b", "--markervaluebits", type=int, help="Amount of bits to be used for markervalue",
  184. default=28)
  185. parser.add_argument("-c", "--checksumbits", type=int, help="Amount of bits to be used for checksum",
  186. default=4)
  187. parser.add_argument("-f", "--reportfetcherclass", help="Name of report fetcher to be used"
  188. " (class name contained in report_fetcher.py)",
  189. default="TracingReportFetcher")
  190. parser.add_argument("-l", "--useplus1", type=bool, help="Use +1 groups",
  191. default=False)
  192. parser.add_argument("-g", "--usefeedbackips", type=bool, help="Use scanner feedback for group clustering",
  193. default=False)
  194. args = parser.parse_args()
  195. AttackUI(args).cmdloop()