1## This file is part of Scapy 2## See http://www.secdev.org/projects/scapy for more informations 3## Copyright (C) Philippe Biondi <phil@secdev.org> 4## This program is published under a GPLv2 license 5 6""" 7Fields that hold random numbers. 8""" 9 10from __future__ import absolute_import 11import random,time,math 12from scapy.base_classes import Net 13from scapy.compat import * 14from scapy.utils import corrupt_bits,corrupt_bytes 15from scapy.modules.six.moves import range 16 17#################### 18## Random numbers ## 19#################### 20 21 22class RandomEnumeration: 23 """iterate through a sequence in random order. 24 When all the values have been drawn, if forever=1, the drawing is done again. 25 If renewkeys=0, the draw will be in the same order, guaranteeing that the same 26 number will be drawn in not less than the number of integers of the sequence""" 27 def __init__(self, inf, sup, seed=None, forever=1, renewkeys=0): 28 self.forever = forever 29 self.renewkeys = renewkeys 30 self.inf = inf 31 self.rnd = random.Random(seed) 32 self.sbox_size = 256 33 34 self.top = sup-inf+1 35 36 n=0 37 while (1<<n) < self.top: 38 n += 1 39 self.n =n 40 41 self.fs = min(3,(n+1)//2) 42 self.fsmask = 2**self.fs-1 43 self.rounds = max(self.n,3) 44 self.turns = 0 45 self.i = 0 46 47 def __iter__(self): 48 return self 49 def next(self): 50 while True: 51 if self.turns == 0 or (self.i == 0 and self.renewkeys): 52 self.cnt_key = self.rnd.randint(0,2**self.n-1) 53 self.sbox = [self.rnd.randint(0, self.fsmask) 54 for _ in range(self.sbox_size)] 55 self.turns += 1 56 while self.i < 2**self.n: 57 ct = self.i^self.cnt_key 58 self.i += 1 59 for _ in range(self.rounds): # Unbalanced Feistel Network 60 lsb = ct & self.fsmask 61 ct >>= self.fs 62 lsb ^= self.sbox[ct%self.sbox_size] 63 ct |= lsb << (self.n-self.fs) 64 65 if ct < self.top: 66 return self.inf+ct 67 self.i = 0 68 if not self.forever: 69 raise StopIteration 70 __next__ = next 71 72 73class VolatileValue: 74 def __repr__(self): 75 return "<%s>" % self.__class__.__name__ 76 def __eq__(self, other): 77 x = self._fix() 78 y = other._fix() if isinstance(other, VolatileValue) else other 79 if not isinstance(x, type(y)): 80 return False 81 return x == y 82 def __getattr__(self, attr): 83 if attr in ["__setstate__", "__getstate__"]: 84 raise AttributeError(attr) 85 return getattr(self._fix(),attr) 86 def __str__(self): 87 return str(self._fix()) 88 def __bytes__(self): 89 return raw(self._fix()) 90 def __len__(self): 91 return len(self._fix()) 92 93 def _fix(self): 94 return None 95 96 97class RandField(VolatileValue): 98 pass 99 100class RandNum(RandField): 101 """Instances evaluate to random integers in selected range""" 102 min = 0 103 max = 0 104 def __init__(self, min, max): 105 self.min = min 106 self.max = max 107 def _fix(self): 108 return random.randrange(self.min, self.max+1) 109 110 def __int__(self): 111 return int(self._fix()) 112 def __index__(self): 113 return int(self) 114 def __add__(self, other): 115 return self._fix() + other 116 def __radd__(self, other): 117 return other + self._fix() 118 def __sub__(self, other): 119 return self._fix() - other 120 def __rsub__(self, other): 121 return other - self._fix() 122 def __mul__(self, other): 123 return self._fix() * other 124 def __rmul__(self, other): 125 return other * self._fix() 126 def __floordiv__(self, other): 127 return self._fix() / other 128 __div__ = __floordiv__ 129 130class RandNumGamma(RandNum): 131 def __init__(self, alpha, beta): 132 self.alpha = alpha 133 self.beta = beta 134 def _fix(self): 135 return int(round(random.gammavariate(self.alpha, self.beta))) 136 137class RandNumGauss(RandNum): 138 def __init__(self, mu, sigma): 139 self.mu = mu 140 self.sigma = sigma 141 def _fix(self): 142 return int(round(random.gauss(self.mu, self.sigma))) 143 144class RandNumExpo(RandNum): 145 def __init__(self, lambd, base=0): 146 self.lambd = lambd 147 self.base = base 148 def _fix(self): 149 return self.base+int(round(random.expovariate(self.lambd))) 150 151class RandEnum(RandNum): 152 """Instances evaluate to integer sampling without replacement from the given interval""" 153 def __init__(self, min, max, seed=None): 154 self.seq = RandomEnumeration(min,max,seed) 155 def _fix(self): 156 return next(self.seq) 157 158class RandByte(RandNum): 159 def __init__(self): 160 RandNum.__init__(self, 0, 2**8-1) 161 162class RandSByte(RandNum): 163 def __init__(self): 164 RandNum.__init__(self, -2**7, 2**7-1) 165 166class RandShort(RandNum): 167 def __init__(self): 168 RandNum.__init__(self, 0, 2**16-1) 169 170class RandSShort(RandNum): 171 def __init__(self): 172 RandNum.__init__(self, -2**15, 2**15-1) 173 174class RandInt(RandNum): 175 def __init__(self): 176 RandNum.__init__(self, 0, 2**32-1) 177 178class RandSInt(RandNum): 179 def __init__(self): 180 RandNum.__init__(self, -2**31, 2**31-1) 181 182class RandLong(RandNum): 183 def __init__(self): 184 RandNum.__init__(self, 0, 2**64-1) 185 186class RandSLong(RandNum): 187 def __init__(self): 188 RandNum.__init__(self, -2**63, 2**63-1) 189 190class RandEnumByte(RandEnum): 191 def __init__(self): 192 RandEnum.__init__(self, 0, 2**8-1) 193 194class RandEnumSByte(RandEnum): 195 def __init__(self): 196 RandEnum.__init__(self, -2**7, 2**7-1) 197 198class RandEnumShort(RandEnum): 199 def __init__(self): 200 RandEnum.__init__(self, 0, 2**16-1) 201 202class RandEnumSShort(RandEnum): 203 def __init__(self): 204 RandEnum.__init__(self, -2**15, 2**15-1) 205 206class RandEnumInt(RandEnum): 207 def __init__(self): 208 RandEnum.__init__(self, 0, 2**32-1) 209 210class RandEnumSInt(RandEnum): 211 def __init__(self): 212 RandEnum.__init__(self, -2**31, 2**31-1) 213 214class RandEnumLong(RandEnum): 215 def __init__(self): 216 RandEnum.__init__(self, 0, 2**64-1) 217 218class RandEnumSLong(RandEnum): 219 def __init__(self): 220 RandEnum.__init__(self, -2**63, 2**63-1) 221 222class RandEnumKeys(RandEnum): 223 """Picks a random value from dict keys list. """ 224 def __init__(self, enum, seed=None): 225 self.enum = list(enum) 226 self.seq = RandomEnumeration(0, len(self.enum) - 1, seed) 227 228 def _fix(self): 229 return self.enum[next(self.seq)] 230 231class RandChoice(RandField): 232 def __init__(self, *args): 233 if not args: 234 raise TypeError("RandChoice needs at least one choice") 235 self._choice = args 236 def _fix(self): 237 return random.choice(self._choice) 238 239class RandString(RandField): 240 def __init__(self, size=None, chars="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"): 241 if size is None: 242 size = RandNumExpo(0.01) 243 self.size = size 244 self.chars = chars 245 def _fix(self): 246 s = "" 247 for _ in range(self.size): 248 s += random.choice(self.chars) 249 return s 250 def __mul__(self, n): 251 return self._fix()*n 252 253class RandBin(RandString): 254 def __init__(self, size=None): 255 RandString.__init__(self, size, "".join(map(chr, range(256)))) 256 257 258class RandTermString(RandString): 259 def __init__(self, size, term): 260 RandString.__init__(self, size, "".join(map(chr, range(1,256)))) 261 self.term = term 262 def _fix(self): 263 return RandString._fix(self)+self.term 264 265 def __str__(self): 266 return str(self._fix()) 267 268 def __bytes__(self): 269 return raw(self._fix()) 270 271 272class RandIP(RandString): 273 def __init__(self, iptemplate="0.0.0.0/0"): 274 self.ip = Net(iptemplate) 275 def _fix(self): 276 return self.ip.choice() 277 278class RandMAC(RandString): 279 def __init__(self, template="*"): 280 template += ":*:*:*:*:*" 281 template = template.split(":") 282 self.mac = () 283 for i in range(6): 284 if template[i] == "*": 285 v = RandByte() 286 elif "-" in template[i]: 287 x,y = template[i].split("-") 288 v = RandNum(int(x,16), int(y,16)) 289 else: 290 v = int(template[i],16) 291 self.mac += (v,) 292 def _fix(self): 293 return "%02x:%02x:%02x:%02x:%02x:%02x" % self.mac 294 295class RandIP6(RandString): 296 def __init__(self, ip6template="**"): 297 self.tmpl = ip6template 298 self.sp = self.tmpl.split(":") 299 for i,v in enumerate(self.sp): 300 if not v or v == "**": 301 continue 302 if "-" in v: 303 a,b = v.split("-") 304 elif v == "*": 305 a=b="" 306 else: 307 a=b=v 308 309 if not a: 310 a = "0" 311 if not b: 312 b = "ffff" 313 if a==b: 314 self.sp[i] = int(a,16) 315 else: 316 self.sp[i] = RandNum(int(a,16), int(b,16)) 317 self.variable = "" in self.sp 318 self.multi = self.sp.count("**") 319 def _fix(self): 320 done = 0 321 nbm = self.multi 322 ip = [] 323 for i,n in enumerate(self.sp): 324 if n == "**": 325 nbm -= 1 326 remain = 8-(len(self.sp)-i-1)-len(ip)+nbm 327 if "" in self.sp: 328 remain += 1 329 if nbm or self.variable: 330 remain = random.randint(0,remain) 331 for j in range(remain): 332 ip.append("%04x" % random.randint(0,65535)) 333 elif isinstance(n, RandNum): 334 ip.append("%04x" % n) 335 elif n == 0: 336 ip.append("0") 337 elif not n: 338 ip.append("") 339 else: 340 ip.append("%04x" % n) 341 if len(ip) == 9: 342 ip.remove("") 343 if ip[-1] == "": 344 ip[-1] = "0" 345 return ":".join(ip) 346 347class RandOID(RandString): 348 def __init__(self, fmt=None, depth=RandNumExpo(0.1), idnum=RandNumExpo(0.01)): 349 self.ori_fmt = fmt 350 if fmt is not None: 351 fmt = fmt.split(".") 352 for i in range(len(fmt)): 353 if "-" in fmt[i]: 354 fmt[i] = tuple(map(int, fmt[i].split("-"))) 355 self.fmt = fmt 356 self.depth = depth 357 self.idnum = idnum 358 def __repr__(self): 359 if self.ori_fmt is None: 360 return "<%s>" % self.__class__.__name__ 361 else: 362 return "<%s [%s]>" % (self.__class__.__name__, self.ori_fmt) 363 def _fix(self): 364 if self.fmt is None: 365 return ".".join(str(self.idnum) for _ in range(1 + self.depth)) 366 else: 367 oid = [] 368 for i in self.fmt: 369 if i == "*": 370 oid.append(str(self.idnum)) 371 elif i == "**": 372 oid += [str(self.idnum) for i in range(1 + self.depth)] 373 elif isinstance(i, tuple): 374 oid.append(str(random.randrange(*i))) 375 else: 376 oid.append(i) 377 return ".".join(oid) 378 379 380class RandRegExp(RandField): 381 def __init__(self, regexp, lambda_=0.3,): 382 self._regexp = regexp 383 self._lambda = lambda_ 384 385 @staticmethod 386 def choice_expand(s): #XXX does not support special sets like (ex ':alnum:') 387 m = "" 388 invert = s and s[0] == "^" 389 while True: 390 p = s.find("-") 391 if p < 0: 392 break 393 if p == 0 or p == len(s)-1: 394 m = "-" 395 if p: 396 s = s[:-1] 397 else: 398 s = s[1:] 399 else: 400 c1 = s[p-1] 401 c2 = s[p+1] 402 rng = "".join(map(chr, range(ord(c1), ord(c2)+1))) 403 s = s[:p-1]+rng+s[p+1:] 404 res = m+s 405 if invert: 406 res = "".join(chr(x) for x in range(256) if chr(x) not in res) 407 return res 408 409 @staticmethod 410 def stack_fix(lst, index): 411 r = "" 412 mul = 1 413 for e in lst: 414 if isinstance(e, list): 415 if mul != 1: 416 mul = mul-1 417 r += RandRegExp.stack_fix(e[1:]*mul, index) 418 # only the last iteration should be kept for back reference 419 f = RandRegExp.stack_fix(e[1:], index) 420 for i,idx in enumerate(index): 421 if e is idx: 422 index[i] = f 423 r += f 424 mul = 1 425 elif isinstance(e, tuple): 426 kind,val = e 427 if kind == "cite": 428 r += index[val-1] 429 elif kind == "repeat": 430 mul = val 431 432 elif kind == "choice": 433 if mul == 1: 434 c = random.choice(val) 435 r += RandRegExp.stack_fix(c[1:], index) 436 else: 437 r += RandRegExp.stack_fix([e]*mul, index) 438 mul = 1 439 else: 440 if mul != 1: 441 r += RandRegExp.stack_fix([e]*mul, index) 442 mul = 1 443 else: 444 r += str(e) 445 return r 446 447 def _fix(self): 448 stack = [None] 449 index = [] 450 current = stack 451 i = 0 452 ln = len(self._regexp) 453 interp = True 454 while i < ln: 455 c = self._regexp[i] 456 i+=1 457 458 if c == '(': 459 current = [current] 460 current[0].append(current) 461 elif c == '|': 462 p = current[0] 463 ch = p[-1] 464 if not isinstance(ch, tuple): 465 ch = ("choice",[current]) 466 p[-1] = ch 467 else: 468 ch[1].append(current) 469 current = [p] 470 elif c == ')': 471 ch = current[0][-1] 472 if isinstance(ch, tuple): 473 ch[1].append(current) 474 index.append(current) 475 current = current[0] 476 elif c == '[' or c == '{': 477 current = [current] 478 current[0].append(current) 479 interp = False 480 elif c == ']': 481 current = current[0] 482 choice = RandRegExp.choice_expand("".join(current.pop()[1:])) 483 current.append(RandChoice(*list(choice))) 484 interp = True 485 elif c == '}': 486 current = current[0] 487 num = "".join(current.pop()[1:]) 488 e = current.pop() 489 if "," not in num: 490 n = int(num) 491 current.append([current]+[e]*n) 492 else: 493 num_min,num_max = num.split(",") 494 if not num_min: 495 num_min = "0" 496 if num_max: 497 n = RandNum(int(num_min),int(num_max)) 498 else: 499 n = RandNumExpo(self._lambda,base=int(num_min)) 500 current.append(("repeat",n)) 501 current.append(e) 502 interp = True 503 elif c == '\\': 504 c = self._regexp[i] 505 if c == "s": 506 c = RandChoice(" ","\t") 507 elif c in "0123456789": 508 c = ("cite",ord(c)-0x30) 509 current.append(c) 510 i += 1 511 elif not interp: 512 current.append(c) 513 elif c == '+': 514 e = current.pop() 515 current.append([current]+[e]*(int(random.expovariate(self._lambda))+1)) 516 elif c == '*': 517 e = current.pop() 518 current.append([current]+[e]*int(random.expovariate(self._lambda))) 519 elif c == '?': 520 if random.randint(0,1): 521 current.pop() 522 elif c == '.': 523 current.append(RandChoice(*[chr(x) for x in range(256)])) 524 elif c == '$' or c == '^': 525 pass 526 else: 527 current.append(c) 528 529 return RandRegExp.stack_fix(stack[1:], index) 530 def __repr__(self): 531 return "<%s [%r]>" % (self.__class__.__name__, self._regexp) 532 533class RandSingularity(RandChoice): 534 pass 535 536class RandSingNum(RandSingularity): 537 @staticmethod 538 def make_power_of_two(end): 539 sign = 1 540 if end == 0: 541 end = 1 542 if end < 0: 543 end = -end 544 sign = -1 545 end_n = int(math.log(end)/math.log(2))+1 546 return {sign*2**i for i in range(end_n)} 547 548 def __init__(self, mn, mx): 549 sing = {0, mn, mx, int((mn+mx)/2)} 550 sing |= self.make_power_of_two(mn) 551 sing |= self.make_power_of_two(mx) 552 for i in sing.copy(): 553 sing.add(i+1) 554 sing.add(i-1) 555 for i in sing.copy(): 556 if not mn <= i <= mx: 557 sing.remove(i) 558 self._choice = list(sing) 559 self._choice.sort() 560 561 562class RandSingByte(RandSingNum): 563 def __init__(self): 564 RandSingNum.__init__(self, 0, 2**8-1) 565 566class RandSingSByte(RandSingNum): 567 def __init__(self): 568 RandSingNum.__init__(self, -2**7, 2**7-1) 569 570class RandSingShort(RandSingNum): 571 def __init__(self): 572 RandSingNum.__init__(self, 0, 2**16-1) 573 574class RandSingSShort(RandSingNum): 575 def __init__(self): 576 RandSingNum.__init__(self, -2**15, 2**15-1) 577 578class RandSingInt(RandSingNum): 579 def __init__(self): 580 RandSingNum.__init__(self, 0, 2**32-1) 581 582class RandSingSInt(RandSingNum): 583 def __init__(self): 584 RandSingNum.__init__(self, -2**31, 2**31-1) 585 586class RandSingLong(RandSingNum): 587 def __init__(self): 588 RandSingNum.__init__(self, 0, 2**64-1) 589 590class RandSingSLong(RandSingNum): 591 def __init__(self): 592 RandSingNum.__init__(self, -2**63, 2**63-1) 593 594class RandSingString(RandSingularity): 595 def __init__(self): 596 self._choice = [ "", 597 "%x", 598 "%%", 599 "%s", 600 "%i", 601 "%n", 602 "%x%x%x%x%x%x%x%x%x", 603 "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", 604 "%", 605 "%%%", 606 "A"*4096, 607 b"\x00"*4096, 608 b"\xff"*4096, 609 b"\x7f"*4096, 610 b"\x80"*4096, 611 " "*4096, 612 "\\"*4096, 613 "("*4096, 614 "../"*1024, 615 "/"*1024, 616 "${HOME}"*512, 617 " or 1=1 --", 618 "' or 1=1 --", 619 '" or 1=1 --', 620 " or 1=1; #", 621 "' or 1=1; #", 622 '" or 1=1; #', 623 ";reboot;", 624 "$(reboot)", 625 "`reboot`", 626 "index.php%00", 627 b"\x00", 628 "%00", 629 "\\", 630 "../../../../../../../../../../../../../../../../../etc/passwd", 631 "%2e%2e%2f" * 20 + "etc/passwd", 632 "%252e%252e%252f" * 20 + "boot.ini", 633 "..%c0%af" * 20 + "etc/passwd", 634 "..%c0%af" * 20 + "boot.ini", 635 "//etc/passwd", 636 r"..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\boot.ini", 637 "AUX:", 638 "CLOCK$", 639 "COM:", 640 "CON:", 641 "LPT:", 642 "LST:", 643 "NUL:", 644 "CON:", 645 r"C:\CON\CON", 646 r"C:\boot.ini", 647 r"\\myserver\share", 648 "foo.exe:", 649 "foo.exe\\", ] 650 651 def __str__(self): 652 return str(self._fix()) 653 def __bytes__(self): 654 return raw(self._fix()) 655 656 657class RandPool(RandField): 658 def __init__(self, *args): 659 """Each parameter is a volatile object or a couple (volatile object, weight)""" 660 pool = [] 661 for p in args: 662 w = 1 663 if isinstance(p, tuple): 664 p,w = p 665 pool += [p]*w 666 self._pool = pool 667 def _fix(self): 668 r = random.choice(self._pool) 669 return r._fix() 670 671# Automatic timestamp 672 673class AutoTime(VolatileValue): 674 def __init__(self, base=None): 675 if base == None: 676 self.diff = 0 677 else: 678 self.diff = time.time()-base 679 def _fix(self): 680 return time.time()-self.diff 681 682class IntAutoTime(AutoTime): 683 def _fix(self): 684 return int(time.time()-self.diff) 685 686 687class ZuluTime(AutoTime): 688 def __init__(self, diff=0): 689 self.diff = diff 690 def _fix(self): 691 return time.strftime("%y%m%d%H%M%SZ", 692 time.gmtime(time.time() + self.diff)) 693 694 695class GeneralizedTime(AutoTime): 696 def __init__(self, diff=0): 697 self.diff = diff 698 def _fix(self): 699 return time.strftime("%Y%m%d%H%M%SZ", 700 time.gmtime(time.time() + self.diff)) 701 702 703class DelayedEval(VolatileValue): 704 """ Example of usage: DelayedEval("time.time()") """ 705 def __init__(self, expr): 706 self.expr = expr 707 def _fix(self): 708 return eval(self.expr) 709 710 711class IncrementalValue(VolatileValue): 712 def __init__(self, start=0, step=1, restart=-1): 713 self.start = self.val = start 714 self.step = step 715 self.restart = restart 716 def _fix(self): 717 v = self.val 718 if self.val == self.restart : 719 self.val = self.start 720 else: 721 self.val += self.step 722 return v 723 724class CorruptedBytes(VolatileValue): 725 def __init__(self, s, p=0.01, n=None): 726 self.s = s 727 self.p = p 728 self.n = n 729 def _fix(self): 730 return corrupt_bytes(self.s, self.p, self.n) 731 732class CorruptedBits(CorruptedBytes): 733 def _fix(self): 734 return corrupt_bits(self.s, self.p, self.n) 735 736