1# SPDX-License-Identifier: GPL-2.0-only 2# This file is part of Scapy 3# See https://scapy.net/ for more information 4# Copyright (C) Philippe Biondi <phil@secdev.org> 5# Copyright (C) Michael Farrell <micolous+git@gmail.com> 6# Copyright (C) Gauthier Sebaux 7 8""" 9Fields that hold random numbers. 10""" 11 12import copy 13import random 14import time 15import math 16import re 17import uuid 18import struct 19import string 20 21from scapy.base_classes import Net 22from scapy.compat import bytes_encode, chb, plain_str 23from scapy.utils import corrupt_bits, corrupt_bytes 24 25from typing import ( 26 List, 27 TypeVar, 28 Generic, 29 Set, 30 Union, 31 Any, 32 Dict, 33 Optional, 34 Tuple, 35 cast, 36) 37 38#################### 39# Random numbers # 40#################### 41 42 43class RandomEnumeration: 44 """iterate through a sequence in random order. 45 When all the values have been drawn, if forever=1, the drawing is done again. # noqa: E501 46 If renewkeys=0, the draw will be in the same order, guaranteeing that the same # noqa: E501 47 number will be drawn in not less than the number of integers of the sequence""" # noqa: E501 48 49 def __init__(self, inf, sup, seed=None, forever=1, renewkeys=0): 50 # type: (int, int, Optional[int], int, int) -> None 51 self.forever = forever 52 self.renewkeys = renewkeys 53 self.inf = inf 54 self.rnd = random.Random(seed) 55 self.sbox_size = 256 56 57 self.top = sup - inf + 1 58 59 n = 0 60 while (1 << n) < self.top: 61 n += 1 62 self.n = n 63 64 self.fs = min(3, (n + 1) // 2) 65 self.fsmask = 2**self.fs - 1 66 self.rounds = max(self.n, 3) 67 self.turns = 0 68 self.i = 0 69 70 def __iter__(self): 71 # type: () -> RandomEnumeration 72 return self 73 74 def next(self): 75 # type: () -> int 76 while True: 77 if self.turns == 0 or (self.i == 0 and self.renewkeys): 78 self.cnt_key = self.rnd.randint(0, 2**self.n - 1) 79 self.sbox = [self.rnd.randint(0, self.fsmask) 80 for _ in range(self.sbox_size)] 81 self.turns += 1 82 while self.i < 2**self.n: 83 ct = self.i ^ self.cnt_key 84 self.i += 1 85 for _ in range(self.rounds): # Unbalanced Feistel Network 86 lsb = ct & self.fsmask 87 ct >>= self.fs 88 lsb ^= self.sbox[ct % self.sbox_size] 89 ct |= lsb << (self.n - self.fs) 90 91 if ct < self.top: 92 return self.inf + ct 93 self.i = 0 94 if not self.forever: 95 raise StopIteration 96 __next__ = next 97 98 99_T = TypeVar('_T') 100 101 102class VolatileValue(Generic[_T]): 103 def __repr__(self): 104 # type: () -> str 105 return "<%s>" % self.__class__.__name__ 106 107 def _command_args(self): 108 # type: () -> str 109 return '' 110 111 def command(self, json=False): 112 # type: (bool) -> Union[Dict[str, str], str] 113 if json: 114 return {"type": self.__class__.__name__, "value": self._command_args()} 115 else: 116 return "%s(%s)" % (self.__class__.__name__, self._command_args()) 117 118 def __eq__(self, other): 119 # type: (Any) -> bool 120 x = self._fix() 121 y = other._fix() if isinstance(other, VolatileValue) else other 122 if not isinstance(x, type(y)): 123 return False 124 return bool(x == y) 125 126 def __ne__(self, other): 127 # type: (Any) -> bool 128 # Python 2.7 compat 129 return not self == other 130 131 __hash__ = None # type: ignore 132 133 def __getattr__(self, attr): 134 # type: (str) -> Any 135 if attr in ["__setstate__", "__getstate__"]: 136 raise AttributeError(attr) 137 return getattr(self._fix(), attr) 138 139 def __str__(self): 140 # type: () -> str 141 return str(self._fix()) 142 143 def __bytes__(self): 144 # type: () -> bytes 145 return bytes_encode(self._fix()) 146 147 def __len__(self): 148 # type: () -> int 149 # Does not work for some types (int?) 150 return len(self._fix()) # type: ignore 151 152 def copy(self): 153 # type: () -> Any 154 return copy.copy(self) 155 156 def _fix(self): 157 # type: () -> _T 158 return cast(_T, None) 159 160 161class RandField(VolatileValue[_T], Generic[_T]): 162 pass 163 164 165_I = TypeVar("_I", int, float) 166 167 168class _RandNumeral(RandField[_I]): 169 """Implements integer management in RandField""" 170 171 def __int__(self): 172 # type: () -> int 173 return int(self._fix()) 174 175 def __index__(self): 176 # type: () -> int 177 return int(self) 178 179 def __nonzero__(self): 180 # type: () -> bool 181 return bool(self._fix()) 182 __bool__ = __nonzero__ 183 184 def __add__(self, other): 185 # type: (_I) -> _I 186 return self._fix() + other 187 188 def __radd__(self, other): 189 # type: (_I) -> _I 190 return other + self._fix() 191 192 def __sub__(self, other): 193 # type: (_I) -> _I 194 return self._fix() - other 195 196 def __rsub__(self, other): 197 # type: (_I) -> _I 198 return other - self._fix() 199 200 def __mul__(self, other): 201 # type: (_I) -> _I 202 return self._fix() * other 203 204 def __rmul__(self, other): 205 # type: (_I) -> _I 206 return other * self._fix() 207 208 def __floordiv__(self, other): 209 # type: (_I) -> float 210 return self._fix() / other 211 __div__ = __floordiv__ 212 213 def __lt__(self, other): 214 # type: (_I) -> bool 215 return self._fix() < other 216 217 def __le__(self, other): 218 # type: (_I) -> bool 219 return self._fix() <= other 220 221 def __ge__(self, other): 222 # type: (_I) -> bool 223 return self._fix() >= other 224 225 def __gt__(self, other): 226 # type: (_I) -> bool 227 return self._fix() > other 228 229 230class RandNum(_RandNumeral[int]): 231 """Instances evaluate to random integers in selected range""" 232 min = 0 233 max = 0 234 235 def __init__(self, min, max): 236 # type: (int, int) -> None 237 self.min = min 238 self.max = max 239 240 def _command_args(self): 241 # type: () -> str 242 if self.__class__.__name__ == 'RandNum': 243 return "min=%r, max=%r" % (self.min, self.max) 244 return super(RandNum, self)._command_args() 245 246 def _fix(self): 247 # type: () -> int 248 return random.randrange(self.min, self.max + 1) 249 250 def __lshift__(self, other): 251 # type: (int) -> int 252 return self._fix() << other 253 254 def __rshift__(self, other): 255 # type: (int) -> int 256 return self._fix() >> other 257 258 def __and__(self, other): 259 # type: (int) -> int 260 return self._fix() & other 261 262 def __rand__(self, other): 263 # type: (int) -> int 264 return other & self._fix() 265 266 def __or__(self, other): 267 # type: (int) -> int 268 return self._fix() | other 269 270 def __ror__(self, other): 271 # type: (int) -> int 272 return other | self._fix() 273 274 275class RandFloat(_RandNumeral[float]): 276 def __init__(self, min, max): 277 # type: (int, int) -> None 278 self.min = min 279 self.max = max 280 281 def _fix(self): 282 # type: () -> float 283 return random.uniform(self.min, self.max) 284 285 286class RandBinFloat(RandFloat): 287 def _fix(self): 288 # type: () -> float 289 return cast( 290 float, 291 struct.unpack("!f", bytes(RandBin(4)))[0] 292 ) 293 294 295class RandNumGamma(RandNum): 296 def __init__(self, alpha, beta): 297 # type: (int, int) -> None 298 self.alpha = alpha 299 self.beta = beta 300 301 def _command_args(self): 302 # type: () -> str 303 return "alpha=%r, beta=%r" % (self.alpha, self.beta) 304 305 def _fix(self): 306 # type: () -> int 307 return int(round(random.gammavariate(self.alpha, self.beta))) 308 309 310class RandNumGauss(RandNum): 311 def __init__(self, mu, sigma): 312 # type: (int, int) -> None 313 self.mu = mu 314 self.sigma = sigma 315 316 def _command_args(self): 317 # type: () -> str 318 return "mu=%r, sigma=%r" % (self.mu, self.sigma) 319 320 def _fix(self): 321 # type: () -> int 322 return int(round(random.gauss(self.mu, self.sigma))) 323 324 325class RandNumExpo(RandNum): 326 def __init__(self, lambd, base=0): 327 # type: (float, int) -> None 328 self.lambd = lambd 329 self.base = base 330 331 def _command_args(self): 332 # type: () -> str 333 ret = "lambd=%r" % self.lambd 334 if self.base != 0: 335 ret += ", base=%r" % self.base 336 return ret 337 338 def _fix(self): 339 # type: () -> int 340 return self.base + int(round(random.expovariate(self.lambd))) 341 342 343class RandEnum(RandNum): 344 """Instances evaluate to integer sampling without replacement from the given interval""" # noqa: E501 345 346 def __init__(self, min, max, seed=None): 347 # type: (int, int, Optional[int]) -> None 348 self._seed = seed 349 self.seq = RandomEnumeration(min, max, seed) 350 super(RandEnum, self).__init__(min, max) 351 352 def _command_args(self): 353 # type: () -> str 354 ret = "min=%r, max=%r" % (self.min, self.max) 355 if self._seed: 356 ret += ", seed=%r" % self._seed 357 return ret 358 359 def _fix(self): 360 # type: () -> int 361 return next(self.seq) 362 363 364class RandByte(RandNum): 365 def __init__(self): 366 # type: () -> None 367 RandNum.__init__(self, 0, 2**8 - 1) 368 369 370class RandSByte(RandNum): 371 def __init__(self): 372 # type: () -> None 373 RandNum.__init__(self, -2**7, 2**7 - 1) 374 375 376class RandShort(RandNum): 377 def __init__(self): 378 # type: () -> None 379 RandNum.__init__(self, 0, 2**16 - 1) 380 381 382class RandSShort(RandNum): 383 def __init__(self): 384 # type: () -> None 385 RandNum.__init__(self, -2**15, 2**15 - 1) 386 387 388class RandInt(RandNum): 389 def __init__(self): 390 # type: () -> None 391 RandNum.__init__(self, 0, 2**32 - 1) 392 393 394class RandSInt(RandNum): 395 def __init__(self): 396 # type: () -> None 397 RandNum.__init__(self, -2**31, 2**31 - 1) 398 399 400class RandLong(RandNum): 401 def __init__(self): 402 # type: () -> None 403 RandNum.__init__(self, 0, 2**64 - 1) 404 405 406class RandSLong(RandNum): 407 def __init__(self): 408 # type: () -> None 409 RandNum.__init__(self, -2**63, 2**63 - 1) 410 411 412class RandEnumByte(RandEnum): 413 def __init__(self): 414 # type: () -> None 415 RandEnum.__init__(self, 0, 2**8 - 1) 416 417 418class RandEnumSByte(RandEnum): 419 def __init__(self): 420 # type: () -> None 421 RandEnum.__init__(self, -2**7, 2**7 - 1) 422 423 424class RandEnumShort(RandEnum): 425 def __init__(self): 426 # type: () -> None 427 RandEnum.__init__(self, 0, 2**16 - 1) 428 429 430class RandEnumSShort(RandEnum): 431 def __init__(self): 432 # type: () -> None 433 RandEnum.__init__(self, -2**15, 2**15 - 1) 434 435 436class RandEnumInt(RandEnum): 437 def __init__(self): 438 # type: () -> None 439 RandEnum.__init__(self, 0, 2**32 - 1) 440 441 442class RandEnumSInt(RandEnum): 443 def __init__(self): 444 # type: () -> None 445 RandEnum.__init__(self, -2**31, 2**31 - 1) 446 447 448class RandEnumLong(RandEnum): 449 def __init__(self): 450 # type: () -> None 451 RandEnum.__init__(self, 0, 2**64 - 1) 452 453 454class RandEnumSLong(RandEnum): 455 def __init__(self): 456 # type: () -> None 457 RandEnum.__init__(self, -2**63, 2**63 - 1) 458 459 460class RandEnumKeys(RandEnum): 461 """Picks a random value from dict keys list. """ 462 463 def __init__(self, enum, seed=None): 464 # type: (Dict[Any, Any], Optional[int]) -> None 465 self.enum = list(enum) 466 RandEnum.__init__(self, 0, len(self.enum) - 1, seed) 467 468 def _command_args(self): 469 # type: () -> str 470 # Note: only outputs the list of keys, but values are irrelevant anyway 471 ret = "enum=%r" % self.enum 472 if self._seed: 473 ret += ", seed=%r" % self._seed 474 return ret 475 476 def _fix(self): 477 # type: () -> Any 478 return self.enum[next(self.seq)] 479 480 481class RandChoice(RandField[Any]): 482 def __init__(self, *args): 483 # type: (*Any) -> None 484 if not args: 485 raise TypeError("RandChoice needs at least one choice") 486 self._choice = list(args) 487 488 def _command_args(self): 489 # type: () -> str 490 return ", ".join(self._choice) 491 492 def _fix(self): 493 # type: () -> Any 494 return random.choice(self._choice) 495 496 497_S = TypeVar("_S", bytes, str) 498 499 500class _RandString(RandField[_S], Generic[_S]): 501 def __str__(self): 502 # type: () -> str 503 return plain_str(self._fix()) 504 505 def __bytes__(self): 506 # type: () -> bytes 507 return bytes_encode(self._fix()) 508 509 def __mul__(self, n): 510 # type: (int) -> _S 511 return self._fix() * n 512 513 514class RandString(_RandString[str]): 515 _DEFAULT_CHARS = (string.ascii_uppercase + string.ascii_lowercase + 516 string.digits) 517 518 def __init__(self, size=None, chars=_DEFAULT_CHARS): 519 # type: (Optional[Union[int, RandNum]], str) -> None 520 if size is None: 521 size = RandNumExpo(0.01) 522 self.size = size 523 self.chars = chars 524 525 def _command_args(self): 526 # type: () -> str 527 ret = "" 528 if isinstance(self.size, VolatileValue): 529 if self.size.lambd != 0.01 or self.size.base != 0: 530 ret += "size=%r" % self.size.command() 531 else: 532 ret += "size=%r" % self.size 533 534 if self.chars != self._DEFAULT_CHARS: 535 ret += ", chars=%r" % self.chars 536 return ret 537 538 def _fix(self): 539 # type: () -> str 540 s = "" 541 for _ in range(int(self.size)): 542 s += random.choice(self.chars) 543 return s 544 545 546class RandBin(_RandString[bytes]): 547 _DEFAULT_CHARS = b"".join(chb(c) for c in range(256)) 548 549 def __init__(self, size=None, chars=_DEFAULT_CHARS): 550 # type: (Optional[Union[int, RandNum]], bytes) -> None 551 if size is None: 552 size = RandNumExpo(0.01) 553 self.size = size 554 self.chars = chars 555 556 def _command_args(self): 557 # type: () -> str 558 if not isinstance(self.size, VolatileValue): 559 return "size=%r" % self.size 560 561 if isinstance(self.size, RandNumExpo) and \ 562 self.size.lambd == 0.01 and self.size.base == 0: 563 # Default size for RandString, skip 564 return "" 565 return "size=%r" % self.size.command() 566 567 def _fix(self): 568 # type: () -> bytes 569 s = b"" 570 for _ in range(int(self.size)): 571 s += struct.pack("!B", random.choice(self.chars)) 572 return s 573 574 575class RandTermString(RandBin): 576 def __init__(self, size, term): 577 # type: (Union[int, RandNum], bytes) -> None 578 self.term = bytes_encode(term) 579 super(RandTermString, self).__init__(size=size) 580 self.chars = self.chars.replace(self.term, b"") 581 582 def _command_args(self): 583 # type: () -> str 584 return ", ".join((super(RandTermString, self)._command_args(), 585 "term=%r" % self.term)) 586 587 def _fix(self): 588 # type: () -> bytes 589 return RandBin._fix(self) + self.term 590 591 592class RandIP(_RandString[str]): 593 _DEFAULT_IPTEMPLATE = "0.0.0.0/0" 594 595 def __init__(self, iptemplate=_DEFAULT_IPTEMPLATE): 596 # type: (str) -> None 597 super(RandIP, self).__init__() 598 self.ip = Net(iptemplate) 599 600 def _command_args(self): 601 # type: () -> str 602 rep = "%s/%s" % (self.ip.net, self.ip.mask) 603 if rep == self._DEFAULT_IPTEMPLATE: 604 return "" 605 return "iptemplate=%r" % rep 606 607 def _fix(self): 608 # type: () -> str 609 return self.ip.choice() 610 611 612class RandMAC(_RandString[str]): 613 def __init__(self, _template="*"): 614 # type: (str) -> None 615 super(RandMAC, self).__init__() 616 self._template = _template 617 _template += ":*:*:*:*:*" 618 template = _template.split(":") 619 self.mac = () # type: Tuple[Union[int, RandNum], ...] 620 for i in range(6): 621 v = 0 # type: Union[int, RandNum] 622 if template[i] == "*": 623 v = RandByte() 624 elif "-" in template[i]: 625 x, y = template[i].split("-") 626 v = RandNum(int(x, 16), int(y, 16)) 627 else: 628 v = int(template[i], 16) 629 self.mac += (v,) 630 631 def _command_args(self): 632 # type: () -> str 633 if self._template == "*": 634 return "" 635 return "template=%r" % self._template 636 637 def _fix(self): 638 # type: () -> str 639 return "%02x:%02x:%02x:%02x:%02x:%02x" % self.mac # type: ignore 640 641 642class RandIP6(_RandString[str]): 643 def __init__(self, ip6template="**"): 644 # type: (str) -> None 645 super(RandIP6, self).__init__() 646 self.tmpl = ip6template 647 self.sp = [] # type: List[Union[int, RandNum, str]] 648 for v in self.tmpl.split(":"): 649 if not v or v == "**": 650 self.sp.append(v) 651 continue 652 if "-" in v: 653 a, b = v.split("-") 654 elif v == "*": 655 a = b = "" 656 else: 657 a = b = v 658 659 if not a: 660 a = "0" 661 if not b: 662 b = "ffff" 663 if a == b: 664 self.sp.append(int(a, 16)) 665 else: 666 self.sp.append(RandNum(int(a, 16), int(b, 16))) 667 self.variable = "" in self.sp 668 self.multi = self.sp.count("**") 669 670 def _command_args(self): 671 # type: () -> str 672 if self.tmpl == "**": 673 return "" 674 return "ip6template=%r" % self.tmpl 675 676 def _fix(self): 677 # type: () -> str 678 nbm = self.multi 679 ip = [] # type: List[str] 680 for i, n in enumerate(self.sp): 681 if n == "**": 682 nbm -= 1 683 remain = 8 - (len(self.sp) - i - 1) - len(ip) + nbm 684 if "" in self.sp: 685 remain += 1 686 if nbm or self.variable: 687 remain = random.randint(0, remain) 688 for j in range(remain): 689 ip.append("%04x" % random.randint(0, 65535)) 690 elif isinstance(n, RandNum): 691 ip.append("%04x" % int(n)) 692 elif n == 0: 693 ip.append("0") 694 elif not n: 695 ip.append("") 696 else: 697 ip.append("%04x" % int(n)) 698 if len(ip) == 9: 699 ip.remove("") 700 if ip[-1] == "": 701 ip[-1] = "0" 702 return ":".join(ip) 703 704 705class RandOID(_RandString[str]): 706 def __init__(self, fmt=None, depth=RandNumExpo(0.1), idnum=RandNumExpo(0.01)): # noqa: E501 707 # type: (Optional[str], RandNumExpo, RandNumExpo) -> None 708 super(RandOID, self).__init__() 709 self.ori_fmt = fmt 710 self.fmt = None # type: Optional[List[Union[str, Tuple[int, ...]]]] 711 if fmt is not None: 712 self.fmt = [ 713 tuple(map(int, x.split("-"))) if "-" in x else x 714 for x in fmt.split(".") 715 ] 716 self.depth = depth 717 self.idnum = idnum 718 719 def _command_args(self): 720 # type: () -> str 721 ret = [] 722 if self.fmt: 723 ret.append("fmt=%r" % self.ori_fmt) 724 725 if not isinstance(self.depth, VolatileValue): 726 ret.append("depth=%r" % self.depth) 727 elif not isinstance(self.depth, RandNumExpo) or \ 728 self.depth.lambd != 0.1 or self.depth.base != 0: 729 ret.append("depth=%s" % self.depth.command()) 730 731 if not isinstance(self.idnum, VolatileValue): 732 ret.append("idnum=%r" % self.idnum) 733 elif not isinstance(self.idnum, RandNumExpo) or \ 734 self.idnum.lambd != 0.01 or self.idnum.base != 0: 735 ret.append("idnum=%s" % self.idnum.command()) 736 737 return ", ".join(ret) 738 739 def __repr__(self): 740 # type: () -> str 741 if self.ori_fmt is None: 742 return "<%s>" % self.__class__.__name__ 743 else: 744 return "<%s [%s]>" % (self.__class__.__name__, self.ori_fmt) 745 746 def _fix(self): 747 # type: () -> str 748 if self.fmt is None: 749 return ".".join(str(self.idnum) for _ in range(1 + self.depth)) 750 else: 751 oid = [] 752 for i in self.fmt: 753 if i == "*": 754 oid.append(str(self.idnum)) 755 elif i == "**": 756 oid += [str(self.idnum) for i in range(1 + self.depth)] 757 elif isinstance(i, tuple): 758 oid.append(str(random.randrange(*i))) 759 else: 760 oid.append(i) 761 return ".".join(oid) 762 763 764class RandRegExp(RandField[str]): 765 def __init__(self, regexp, lambda_=0.3): 766 # type: (str, float) -> None 767 self._regexp = regexp 768 self._lambda = lambda_ 769 770 def _command_args(self): 771 # type: () -> str 772 ret = "regexp=%r" % self._regexp 773 if self._lambda != 0.3: 774 ret += ", lambda_=%r" % self._lambda 775 return ret 776 777 special_sets = { 778 "[:alnum:]": "[a-zA-Z0-9]", 779 "[:alpha:]": "[a-zA-Z]", 780 "[:ascii:]": "[\x00-\x7F]", 781 "[:blank:]": "[ \t]", 782 "[:cntrl:]": "[\x00-\x1F\x7F]", 783 "[:digit:]": "[0-9]", 784 "[:graph:]": "[\x21-\x7E]", 785 "[:lower:]": "[a-z]", 786 "[:print:]": "[\x20-\x7E]", 787 "[:punct:]": "[!\"\\#$%&'()*+,\\-./:;<=>?@\\[\\\\\\]^_{|}~]", 788 "[:space:]": "[ \t\r\n\v\f]", 789 "[:upper:]": "[A-Z]", 790 "[:word:]": "[A-Za-z0-9_]", 791 "[:xdigit:]": "[A-Fa-f0-9]", 792 } 793 794 @staticmethod 795 def choice_expand(s): 796 # type: (str) -> str 797 m = "" 798 invert = s and s[0] == "^" 799 while True: 800 p = s.find("-") 801 if p < 0: 802 break 803 if p == 0 or p == len(s) - 1: 804 m = "-" 805 if p: 806 s = s[:-1] 807 else: 808 s = s[1:] 809 else: 810 c1 = s[p - 1] 811 c2 = s[p + 1] 812 rng = "".join(map(chr, range(ord(c1), ord(c2) + 1))) 813 s = s[:p - 1] + rng + s[p + 1:] 814 res = m + s 815 if invert: 816 res = "".join(chr(x) for x in range(256) if chr(x) not in res) 817 return res 818 819 @staticmethod 820 def stack_fix(lst, index): 821 # type: (List[Any], List[Any]) -> str 822 r = "" 823 mul = 1 824 for e in lst: 825 if isinstance(e, list): 826 if mul != 1: 827 mul = mul - 1 828 r += RandRegExp.stack_fix(e[1:] * mul, index) 829 # only the last iteration should be kept for back reference 830 f = RandRegExp.stack_fix(e[1:], index) 831 for i, idx in enumerate(index): 832 if e is idx: 833 index[i] = f 834 r += f 835 mul = 1 836 elif isinstance(e, tuple): 837 kind, val = e 838 if kind == "cite": 839 r += index[val - 1] 840 elif kind == "repeat": 841 mul = val 842 843 elif kind == "choice": 844 if mul == 1: 845 c = random.choice(val) 846 r += RandRegExp.stack_fix(c[1:], index) 847 else: 848 r += RandRegExp.stack_fix([e] * mul, index) 849 mul = 1 850 else: 851 if mul != 1: 852 r += RandRegExp.stack_fix([e] * mul, index) 853 mul = 1 854 else: 855 r += str(e) 856 return r 857 858 def _fix(self): 859 # type: () -> str 860 stack = [None] 861 index = [] 862 # Give up on typing this 863 current = stack # type: Any 864 i = 0 865 regexp = self._regexp 866 for k, v in self.special_sets.items(): 867 regexp = regexp.replace(k, v) 868 ln = len(regexp) 869 interp = True 870 while i < ln: 871 c = regexp[i] 872 i += 1 873 874 if c == '(': 875 current = [current] 876 current[0].append(current) 877 elif c == '|': 878 p = current[0] 879 ch = p[-1] 880 if not isinstance(ch, tuple): 881 ch = ("choice", [current]) 882 p[-1] = ch 883 else: 884 ch[1].append(current) 885 current = [p] 886 elif c == ')': 887 ch = current[0][-1] 888 if isinstance(ch, tuple): 889 ch[1].append(current) 890 index.append(current) 891 current = current[0] 892 elif c == '[' or c == '{': 893 current = [current] 894 current[0].append(current) 895 interp = False 896 elif c == ']': 897 current = current[0] 898 choice = RandRegExp.choice_expand("".join(current.pop()[1:])) 899 current.append(RandChoice(*list(choice))) 900 interp = True 901 elif c == '}': 902 current = current[0] 903 num = "".join(current.pop()[1:]) 904 e = current.pop() 905 if "," not in num: 906 current.append([current] + [e] * int(num)) 907 else: 908 num_min, num_max = num.split(",") 909 if not num_min: 910 num_min = "0" 911 if num_max: 912 n = RandNum(int(num_min), int(num_max)) 913 else: 914 n = RandNumExpo(self._lambda, base=int(num_min)) 915 current.append(("repeat", n)) 916 current.append(e) 917 interp = True 918 elif c == '\\': 919 c = regexp[i] 920 if c == "s": 921 current.append(RandChoice(" ", "\t")) 922 elif c in "0123456789": 923 current.append("cite", ord(c) - 0x30) 924 i += 1 925 elif not interp: 926 current.append(c) 927 elif c == '+': 928 e = current.pop() 929 current.append([current] + [e] * (int(random.expovariate(self._lambda)) + 1)) # noqa: E501 930 elif c == '*': 931 e = current.pop() 932 current.append([current] + [e] * int(random.expovariate(self._lambda))) # noqa: E501 933 elif c == '?': 934 if random.randint(0, 1): 935 current.pop() 936 elif c == '.': 937 current.append(RandChoice(*[chr(x) for x in range(256)])) 938 elif c == '$' or c == '^': 939 pass 940 else: 941 current.append(c) 942 943 return RandRegExp.stack_fix(stack[1:], index) 944 945 def __repr__(self): 946 # type: () -> str 947 return "<%s [%r]>" % (self.__class__.__name__, self._regexp) 948 949 950class RandSingularity(RandChoice): 951 pass 952 953 954class RandSingNum(RandSingularity): 955 @staticmethod 956 def make_power_of_two(end): 957 # type: (int) -> Set[int] 958 sign = 1 959 if end == 0: 960 end = 1 961 if end < 0: 962 end = -end 963 sign = -1 964 end_n = int(math.log(end) / math.log(2)) + 1 965 return {sign * 2**i for i in range(end_n)} 966 967 def __init__(self, mn, mx): 968 # type: (int, int) -> None 969 self._mn = mn 970 self._mx = mx 971 sing = {0, mn, mx, int((mn + mx) / 2)} 972 sing |= self.make_power_of_two(mn) 973 sing |= self.make_power_of_two(mx) 974 for i in sing.copy(): 975 sing.add(i + 1) 976 sing.add(i - 1) 977 for i in sing.copy(): 978 if not mn <= i <= mx: 979 sing.remove(i) 980 super(RandSingNum, self).__init__(*sing) 981 self._choice.sort() 982 983 def _command_args(self): 984 # type: () -> str 985 if self.__class__.__name__ == 'RandSingNum': 986 return "mn=%r, mx=%r" % (self._mn, self._mx) 987 return super(RandSingNum, self)._command_args() 988 989 990class RandSingByte(RandSingNum): 991 def __init__(self): 992 # type: () -> None 993 RandSingNum.__init__(self, 0, 2**8 - 1) 994 995 996class RandSingSByte(RandSingNum): 997 def __init__(self): 998 # type: () -> None 999 RandSingNum.__init__(self, -2**7, 2**7 - 1) 1000 1001 1002class RandSingShort(RandSingNum): 1003 def __init__(self): 1004 # type: () -> None 1005 RandSingNum.__init__(self, 0, 2**16 - 1) 1006 1007 1008class RandSingSShort(RandSingNum): 1009 def __init__(self): 1010 # type: () -> None 1011 RandSingNum.__init__(self, -2**15, 2**15 - 1) 1012 1013 1014class RandSingInt(RandSingNum): 1015 def __init__(self): 1016 # type: () -> None 1017 RandSingNum.__init__(self, 0, 2**32 - 1) 1018 1019 1020class RandSingSInt(RandSingNum): 1021 def __init__(self): 1022 # type: () -> None 1023 RandSingNum.__init__(self, -2**31, 2**31 - 1) 1024 1025 1026class RandSingLong(RandSingNum): 1027 def __init__(self): 1028 # type: () -> None 1029 RandSingNum.__init__(self, 0, 2**64 - 1) 1030 1031 1032class RandSingSLong(RandSingNum): 1033 def __init__(self): 1034 # type: () -> None 1035 RandSingNum.__init__(self, -2**63, 2**63 - 1) 1036 1037 1038class RandSingString(RandSingularity): 1039 def __init__(self): 1040 # type: () -> None 1041 choices_list = ["", 1042 "%x", 1043 "%%", 1044 "%s", 1045 "%i", 1046 "%n", 1047 "%x%x%x%x%x%x%x%x%x", 1048 "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", 1049 "%", 1050 "%%%", 1051 "A" * 4096, 1052 b"\x00" * 4096, 1053 b"\xff" * 4096, 1054 b"\x7f" * 4096, 1055 b"\x80" * 4096, 1056 " " * 4096, 1057 "\\" * 4096, 1058 "(" * 4096, 1059 "../" * 1024, 1060 "/" * 1024, 1061 "${HOME}" * 512, 1062 " or 1=1 --", 1063 "' or 1=1 --", 1064 '" or 1=1 --', 1065 " or 1=1; #", 1066 "' or 1=1; #", 1067 '" or 1=1; #', 1068 ";reboot;", 1069 "$(reboot)", 1070 "`reboot`", 1071 "index.php%00", 1072 b"\x00", 1073 "%00", 1074 "\\", 1075 "../../../../../../../../../../../../../../../../../etc/passwd", # noqa: E501 1076 "%2e%2e%2f" * 20 + "etc/passwd", 1077 "%252e%252e%252f" * 20 + "boot.ini", 1078 "..%c0%af" * 20 + "etc/passwd", 1079 "..%c0%af" * 20 + "boot.ini", 1080 "//etc/passwd", 1081 r"..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\boot.ini", # noqa: E501 1082 "AUX:", 1083 "CLOCK$", 1084 "COM:", 1085 "CON:", 1086 "LPT:", 1087 "LST:", 1088 "NUL:", 1089 "CON:", 1090 r"C:\CON\CON", 1091 r"C:\boot.ini", 1092 r"\\myserver\share", 1093 "foo.exe:", 1094 "foo.exe\\", ] 1095 super(RandSingString, self).__init__(*choices_list) 1096 1097 def _command_args(self): 1098 # type: () -> str 1099 return "" 1100 1101 def __str__(self): 1102 # type: () -> str 1103 return str(self._fix()) 1104 1105 def __bytes__(self): 1106 # type: () -> bytes 1107 return bytes_encode(self._fix()) 1108 1109 1110class RandPool(RandField[VolatileValue[Any]]): 1111 def __init__(self, *args): 1112 # type: (*Tuple[VolatileValue[Any], int]) -> None 1113 """Each parameter is a volatile object or a couple (volatile object, weight)""" # noqa: E501 1114 self._args = args 1115 pool = [] # type: List[VolatileValue[Any]] 1116 for p in args: 1117 w = 1 1118 if isinstance(p, tuple): 1119 p, w = p # type: ignore 1120 pool += [cast(VolatileValue[Any], p)] * w 1121 self._pool = pool 1122 1123 def _command_args(self): 1124 # type: () -> str 1125 ret = [] 1126 for p in self._args: 1127 if isinstance(p, tuple): 1128 ret.append("(%s, %r)" % (p[0].command(), p[1])) 1129 else: 1130 ret.append(p.command()) 1131 return ", ".join(ret) 1132 1133 def _fix(self): 1134 # type: () -> Any 1135 r = random.choice(self._pool) 1136 return r._fix() 1137 1138 1139class RandUUID(RandField[uuid.UUID]): 1140 """Generates a random UUID. 1141 1142 By default, this generates a RFC 4122 version 4 UUID (totally random). 1143 1144 See Python's ``uuid`` module documentation for more information. 1145 1146 Args: 1147 template (optional): A template to build the UUID from. Not valid with 1148 any other option. 1149 node (optional): A 48-bit Host ID. Only valid for version 1 (where it 1150 is optional). 1151 clock_seq (optional): An integer of up to 14-bits for the sequence 1152 number. Only valid for version 1 (where it is 1153 optional). 1154 namespace: A namespace identifier, which is also a UUID. Required for 1155 versions 3 and 5, must be omitted otherwise. 1156 name: string, required for versions 3 and 5, must be omitted otherwise. 1157 version: Version of UUID to use (1, 3, 4 or 5). If omitted, attempts to 1158 guess which version to generate, defaulting to version 4 1159 (totally random). 1160 1161 Raises: 1162 ValueError: on invalid constructor arguments 1163 """ 1164 # This was originally scapy.contrib.dce_rpc.RandUUID. 1165 1166 _BASE = "([0-9a-f]{{{0}}}|\\*|[0-9a-f]{{{0}}}:[0-9a-f]{{{0}}})" 1167 _REG = re.compile( 1168 r"^{0}-?{1}-?{1}-?{2}{2}-?{2}{2}{2}{2}{2}{2}$".format( 1169 _BASE.format(8), _BASE.format(4), _BASE.format(2) 1170 ), 1171 re.I 1172 ) 1173 VERSIONS = [1, 3, 4, 5] 1174 1175 def __init__(self, 1176 template=None, # type: Optional[Any] 1177 node=None, # type: Optional[int] 1178 clock_seq=None, # type: Optional[int] 1179 namespace=None, # type: Optional[uuid.UUID] 1180 name=None, # type: Optional[str] 1181 version=None, # type: Optional[Any] 1182 ): 1183 # type: (...) -> None 1184 self._template = template 1185 self._ori_version = version 1186 1187 self.uuid_template = None 1188 self.clock_seq = None 1189 self.namespace = None 1190 self.name = None 1191 self.node = None 1192 self.version = None 1193 1194 if template: 1195 if node or clock_seq or namespace or name or version: 1196 raise ValueError("UUID template must be the only parameter, " 1197 "if specified") 1198 tmp = RandUUID._REG.match(template) 1199 if tmp: 1200 template = tmp.groups() 1201 else: 1202 # Invalid template 1203 raise ValueError("UUID template is invalid") 1204 rnd_f = [RandInt] + [RandShort] * 2 + [RandByte] * 8 1205 uuid_template = [] # type: List[Union[int, RandNum]] 1206 for i, t in enumerate(template): 1207 if t == "*": 1208 uuid_template.append(rnd_f[i]()) 1209 elif ":" in t: 1210 mini, maxi = t.split(":") 1211 uuid_template.append( 1212 RandNum(int(mini, 16), int(maxi, 16)) 1213 ) 1214 else: 1215 uuid_template.append(int(t, 16)) 1216 1217 self.uuid_template = tuple(uuid_template) 1218 else: 1219 if version: 1220 if version not in RandUUID.VERSIONS: 1221 raise ValueError("version is not supported") 1222 else: 1223 self.version = version 1224 else: 1225 # No version specified, try to guess... 1226 # This could be wrong, and cause an error later! 1227 if node or clock_seq: 1228 self.version = 1 1229 elif namespace and name: 1230 self.version = 5 1231 else: 1232 # Don't know, random! 1233 self.version = 4 1234 1235 # We have a version, now do things... 1236 if self.version == 1: 1237 if namespace or name: 1238 raise ValueError("namespace and name may not be used with " 1239 "version 1") 1240 self.node = node 1241 self.clock_seq = clock_seq 1242 elif self.version in (3, 5): 1243 if node or clock_seq: 1244 raise ValueError("node and clock_seq may not be used with " 1245 "version {}".format(self.version)) 1246 1247 self.namespace = namespace 1248 self.name = name 1249 elif self.version == 4: 1250 if namespace or name or node or clock_seq: 1251 raise ValueError("node, clock_seq, node and clock_seq may " 1252 "not be used with version 4. If you " 1253 "did not specify version, you need to " 1254 "specify it explicitly.") 1255 1256 def _command_args(self): 1257 # type: () -> str 1258 ret = [] 1259 if self._template: 1260 ret.append("template=%r" % self._template) 1261 if self.node: 1262 ret.append("node=%r" % self.node) 1263 if self.clock_seq: 1264 ret.append("clock_seq=%r" % self.clock_seq) 1265 if self.namespace: 1266 ret.append("namespace=%r" % self.namespace) 1267 if self.name: 1268 ret.append("name=%r" % self.name) 1269 if self._ori_version: 1270 ret.append("version=%r" % self._ori_version) 1271 return ", ".join(ret) 1272 1273 def _fix(self): 1274 # type: () -> uuid.UUID 1275 if self.uuid_template: 1276 return uuid.UUID(("%08x%04x%04x" + ("%02x" * 8)) 1277 % self.uuid_template) 1278 elif self.version == 1: 1279 return uuid.uuid1(self.node, self.clock_seq) 1280 elif self.version == 3: 1281 if not self.namespace or not self.name: 1282 raise ValueError("Missing namespace or name") 1283 return uuid.uuid3(self.namespace, self.name) 1284 elif self.version == 4: 1285 return uuid.uuid4() 1286 elif self.version == 5: 1287 if not self.namespace or not self.name: 1288 raise ValueError("Missing namespace or name") 1289 return uuid.uuid5(self.namespace, self.name) 1290 else: 1291 raise ValueError("Unhandled version") 1292 1293 1294# Automatic timestamp 1295 1296 1297class _AutoTime(_RandNumeral[_T], # type: ignore 1298 Generic[_T]): 1299 def __init__(self, base=None, diff=None): 1300 # type: (Optional[int], Optional[float]) -> None 1301 self._base = base 1302 self._ori_diff = diff 1303 1304 if diff is not None: 1305 self.diff = diff 1306 elif base is None: 1307 self.diff = 0. 1308 else: 1309 self.diff = time.time() - base 1310 1311 def _command_args(self): 1312 # type: () -> str 1313 ret = [] 1314 if self._base: 1315 ret.append("base=%r" % self._base) 1316 if self._ori_diff: 1317 ret.append("diff=%r" % self._ori_diff) 1318 return ", ".join(ret) 1319 1320 1321class AutoTime(_AutoTime[float]): 1322 def _fix(self): 1323 # type: () -> float 1324 return time.time() - self.diff 1325 1326 1327class IntAutoTime(_AutoTime[int]): 1328 def _fix(self): 1329 # type: () -> int 1330 return int(time.time() - self.diff) 1331 1332 1333class ZuluTime(_AutoTime[str]): 1334 def __init__(self, diff=0): 1335 # type: (int) -> None 1336 super(ZuluTime, self).__init__(diff=diff) 1337 1338 def _fix(self): 1339 # type: () -> str 1340 return time.strftime("%y%m%d%H%M%SZ", 1341 time.gmtime(time.time() + self.diff)) 1342 1343 1344class GeneralizedTime(_AutoTime[str]): 1345 def __init__(self, diff=0): 1346 # type: (int) -> None 1347 super(GeneralizedTime, self).__init__(diff=diff) 1348 1349 def _fix(self): 1350 # type: () -> str 1351 return time.strftime("%Y%m%d%H%M%SZ", 1352 time.gmtime(time.time() + self.diff)) 1353 1354 1355class DelayedEval(VolatileValue[Any]): 1356 """ Example of usage: DelayedEval("time.time()") """ 1357 1358 def __init__(self, expr): 1359 # type: (str) -> None 1360 self.expr = expr 1361 1362 def _command_args(self): 1363 # type: () -> str 1364 return "expr=%r" % self.expr 1365 1366 def _fix(self): 1367 # type: () -> Any 1368 return eval(self.expr) 1369 1370 1371class IncrementalValue(VolatileValue[int]): 1372 def __init__(self, start=0, step=1, restart=-1): 1373 # type: (int, int, int) -> None 1374 self.start = self.val = start 1375 self.step = step 1376 self.restart = restart 1377 1378 def _command_args(self): 1379 # type: () -> str 1380 ret = [] 1381 if self.start: 1382 ret.append("start=%r" % self.start) 1383 if self.step != 1: 1384 ret.append("step=%r" % self.step) 1385 if self.restart != -1: 1386 ret.append("restart=%r" % self.restart) 1387 return ", ".join(ret) 1388 1389 def _fix(self): 1390 # type: () -> int 1391 v = self.val 1392 if self.val == self.restart: 1393 self.val = self.start 1394 else: 1395 self.val += self.step 1396 return v 1397 1398 1399class CorruptedBytes(VolatileValue[bytes]): 1400 def __init__(self, s, p=0.01, n=None): 1401 # type: (str, float, Optional[Any]) -> None 1402 self.s = s 1403 self.p = p 1404 self.n = n 1405 1406 def _command_args(self): 1407 # type: () -> str 1408 ret = [] 1409 ret.append("s=%r" % self.s) 1410 if self.p != 0.01: 1411 ret.append("p=%r" % self.p) 1412 if self.n: 1413 ret.append("n=%r" % self.n) 1414 return ", ".join(ret) 1415 1416 def _fix(self): 1417 # type: () -> bytes 1418 return corrupt_bytes(self.s, self.p, self.n) 1419 1420 1421class CorruptedBits(CorruptedBytes): 1422 def _fix(self): 1423 # type: () -> bytes 1424 return corrupt_bits(self.s, self.p, self.n) 1425