Utility.py 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. import logging
  2. from random import randint, uniform
  3. from datetime import datetime, timedelta, tzinfo
  4. from calendar import timegm
  5. from lea import Lea
  6. from scapy.layers.netbios import *
  7. platforms = {"win7", "win10", "winxp", "win8.1", "macos", "linux", "win8", "winvista", "winnt", "win2000"}
  8. def update_timestamp(timestamp, pps, delay=0):
  9. """
  10. Calculates the next timestamp to be used based on the packet per second rate (pps) and the maximum delay.
  11. :return: Timestamp to be used for the next packet.
  12. """
  13. if delay == 0:
  14. # Calculate request timestamp
  15. # To imitate the bursty behavior of traffic
  16. randomdelay = Lea.fromValFreqsDict({1 / pps: 70, 2 / pps: 20, 5 / pps: 7, 10 / pps: 3})
  17. return timestamp + uniform(1 / pps, randomdelay.random())
  18. else:
  19. # Calculate reply timestamp
  20. randomdelay = Lea.fromValFreqsDict({2 * delay: 70, 3 * delay: 20, 5 * delay: 7, 10 * delay: 3})
  21. return timestamp + uniform(1 / pps + delay, 1 / pps + randomdelay.random())
  22. def getIntervalPPS(complement_interval_pps, timestamp):
  23. """
  24. Gets the packet rate (pps) for a specific time interval.
  25. :param complement_interval_pps: an array of tuples (the last timestamp in the interval, the packet rate in the crresponding interval).
  26. :param timestamp: the timestamp at which the packet rate is required.
  27. :return: the corresponding packet rate (pps) .
  28. """
  29. for row in complement_interval_pps:
  30. if timestamp<=row[0]:
  31. return row[1]
  32. return complement_interval_pps[-1][1] # in case the timstamp > capture max timestamp
  33. def get_nth_random_element(*element_list):
  34. """
  35. Returns the n-th element of every list from an arbitrary number of given lists.
  36. For example, list1 contains IP addresses, list 2 contains MAC addresses. Use of this function ensures that
  37. the n-th IP address uses always the n-th MAC address.
  38. :param element_list: An arbitrary number of lists.
  39. :return: A tuple of the n-th element of every list.
  40. """
  41. range_max = min([len(x) for x in element_list])
  42. if range_max > 0: range_max -= 1
  43. n = randint(0, range_max)
  44. return tuple(x[n] for x in element_list)
  45. def index_increment(number: int, max: int):
  46. if number + 1 < max:
  47. return number + 1
  48. else:
  49. return 0
  50. def get_rnd_os():
  51. """
  52. Chooses random platform over an operating system probability distribution
  53. :return: random platform as string
  54. """
  55. os_dist = Lea.fromValFreqsDict({"win7": 48.43, "win10": 27.99, "winxp": 6.07, "win8.1": 6.07, "macos": 5.94,
  56. "linux": 3.38, "win8": 1.35, "winvista": 0.46, "winnt": 0.31})
  57. return os_dist.random()
  58. def check_platform(platform: str):
  59. """
  60. Checks if the given platform is currently supported
  61. if not exits with error
  62. :param platform: the platform, which should be validated
  63. """
  64. if platform not in platforms:
  65. print("\nERROR: Invalid platform: " + platform + "." +
  66. "\n Please select one of the following platforms: ", platforms)
  67. exit(1)
  68. def get_ip_range(start_ip: str, end_ip: str):
  69. """
  70. Generates a list of IPs of a given range. If the start_ip is greater than the end_ip, the reverse range is generated
  71. :param start_ip: the start_ip of the desired IP-range
  72. :param end_ip: the end_ip of the desired IP-range
  73. :return: a list of all IPs in the desired IP-range, including start-/end_ip
  74. """
  75. start = ipaddress.ip_address(start_ip)
  76. end = ipaddress.ip_address(end_ip)
  77. ips = []
  78. if start < end:
  79. while start <= end:
  80. ips.append(start.exploded)
  81. start = start+1
  82. elif start > end:
  83. while start >= end:
  84. ips.append(start.exploded)
  85. start = start-1
  86. else:
  87. ips.append(start_ip)
  88. return ips
  89. def generate_source_port_from_platform(platform: str, previousPort=0):
  90. """
  91. Generates the next source port according to the TCP-port-selection strategy of the given platform
  92. :param platform: the platform for which to generate source ports
  93. :param previousPort: the previously used/generated source port. Must be 0 if no port was generated before
  94. :return: the next source port for the given platform
  95. """
  96. check_platform(platform)
  97. if platform in {"winnt", "winxp", "win2000"}:
  98. if (previousPort == 0) or (previousPort + 1 > 5000):
  99. return randint(1024, 5000)
  100. else:
  101. return previousPort + 1
  102. elif platform == "linux":
  103. return randint(32768, 61000)
  104. else:
  105. if (previousPort == 0) or (previousPort + 1 > 65535):
  106. return randint(49152, 65535)
  107. else:
  108. return previousPort + 1
  109. def get_filetime_format(timestamp):
  110. """
  111. Converts a timestamp into MS FILETIME format
  112. :param timestamp: a timestamp in seconds
  113. :return: MS FILETIME timestamp
  114. """
  115. boot_datetime = datetime.fromtimestamp(timestamp)
  116. if boot_datetime.tzinfo is None or boot_datetime.tzinfo.utcoffset(boot_datetime) is None:
  117. boot_datetime = boot_datetime.replace(tzinfo=boot_datetime.tzname())
  118. boot_filetime = 116444736000000000 + (timegm(boot_datetime.timetuple()) * 10000000)
  119. return boot_filetime + (boot_datetime.microsecond * 10)
  120. def get_rnd_boot_time(timestamp, platform="winxp"):
  121. """
  122. Generates a random boot time based on a given timestamp and operating system
  123. :param timestamp: a timestamp in seconds
  124. :param platform: a platform as string as specified in check_platform above. default is winxp. this param is optional
  125. :return: timestamp of random boot time in seconds since EPOCH
  126. """
  127. check_platform(platform)
  128. if platform is "linux":
  129. uptime_in_days = Lea.fromValFreqsDict({3: 50, 7: 25, 14: 12.5, 31: 6.25, 92: 3.125, 183: 1.5625,
  130. 365: 0.78125, 1461: 0.390625, 2922: 0.390625})
  131. elif platform is "macos":
  132. uptime_in_days = Lea.fromValFreqsDict({7: 50, 14: 25, 31: 12.5, 92: 6.25, 183: 3.125, 365: 3.076171875,
  133. 1461: 0.048828125})
  134. else:
  135. uptime_in_days = Lea.fromValFreqsDict({3: 50, 7: 25, 14: 12.5, 31: 6.25, 92: 3.125, 183: 1.5625,
  136. 365: 0.78125, 1461: 0.78125})
  137. timestamp -= randint(0, uptime_in_days.random()*86400)
  138. return timestamp