Utility.py 6.3 KB

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