test.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. #!/usr/bin/env python3
  2. """Each scapy-based attack mod exposes its <name>ize() entry point and dispatches
  3. without crashing when scapy.send/sr/sr1 are mocked. Real packet emission needs root
  4. and is left to the user; this test only validates the dispatch + packet-building.
  5. """
  6. import sys, importlib, threading, time
  7. err = []
  8. import scapy.all as scapy
  9. calls = {"send": 0, "sendp": 0, "sr": 0, "sr1": 0}
  10. def fake_send(*a, **kw):
  11. calls["send"] += 1
  12. def fake_sendp(*a, **kw):
  13. calls["sendp"] += 1
  14. def fake_sr(*a, **kw):
  15. calls["sr"] += 1
  16. return ([], [])
  17. def fake_sr1(*a, **kw):
  18. calls["sr1"] += 1
  19. return None
  20. scapy.send = fake_send
  21. scapy.sendp = fake_sendp
  22. scapy.sr = fake_sr
  23. scapy.sr1 = fake_sr1
  24. for _name in ('core.mods.ufosyn', 'core.mods.xmas', 'core.mods.ufoack', 'core.mods.uforst',
  25. 'core.mods.droper', 'core.mods.overlap', 'core.mods.pinger', 'core.mods.ufoudp',
  26. 'core.mods.spray', 'core.mods.smurf', 'core.mods.fraggle', 'core.mods.tachyon',
  27. 'core.mods.monlist', 'core.mods.sniper', 'core.mods.nuke',
  28. 'core.mods.memcached', 'core.mods.chargen', 'core.mods.cldap',
  29. 'core.mods.ssdp', 'core.mods.qotd', 'core.mods.tftp',
  30. 'core.mods.wsdisco', 'core.mods.coap', 'core.mods.mssql',
  31. 'core.mods.middlebox', 'core.mods.finflood',
  32. 'core.mods.arms', 'core.mods.plex', 'core.mods.netbios', 'core.mods.ripv1'):
  33. mod = importlib.import_module(_name)
  34. for sym in ('send', 'sendp', 'sr', 'sr1'):
  35. if hasattr(mod, sym):
  36. setattr(mod, sym, getattr(scapy, sym))
  37. SPECS = [
  38. ('core.mods.ufosyn', 'synize', ('127.0.0.1', 80, 2)),
  39. ('core.mods.xmas', 'xmasize', ('127.0.0.1', 80, 2)),
  40. ('core.mods.ufoack', 'ackize', ('127.0.0.1', 80, 2)),
  41. ('core.mods.uforst', 'rstize', ('127.0.0.1', 80, 2)),
  42. ('core.mods.droper', 'droperize', ('127.0.0.1', 80, 2)),
  43. ('core.mods.overlap', 'overlapize', ('127.0.0.1', 80, 2)),
  44. ('core.mods.pinger', 'pingerize', ('127.0.0.1', 80, 2)),
  45. ('core.mods.ufoudp', 'ufoudpize', ('127.0.0.1', 53, 2)),
  46. ('core.mods.tachyon', 'dnsize', ('127.0.0.1', 53, 2)),
  47. ('core.mods.monlist', 'monlistize', ('127.0.0.1', 2)),
  48. ('core.mods.sniper', 'sniperize', ('127.0.0.1', 2)),
  49. ('core.mods.finflood', 'ripperize', ('127.0.0.1', 80, 2)),
  50. ('core.mods.memcached', 'crusherize', ('127.0.0.1', 2)),
  51. ('core.mods.chargen', 'fountainize', ('127.0.0.1', 2)),
  52. ('core.mods.cldap', 'wormholize', ('127.0.0.1', 2)),
  53. ('core.mods.ssdp', 'pulsarize', ('127.0.0.1', 2)),
  54. ('core.mods.qotd', 'oraclize', ('127.0.0.1', 2)),
  55. ('core.mods.tftp', 'cargoize', ('127.0.0.1', 2)),
  56. ('core.mods.wsdisco', 'sonarize', ('127.0.0.1', 2)),
  57. ('core.mods.coap', 'nebulize', ('127.0.0.1', 2)),
  58. ('core.mods.mssql', 'phantomize', ('127.0.0.1', 2)),
  59. ('core.mods.middlebox', 'censorshipize',('127.0.0.1', 2)),
  60. ('core.mods.arms', 'polishize', ('127.0.0.1', 2)),
  61. ('core.mods.plex', 'reelize', ('127.0.0.1', 2)),
  62. ('core.mods.netbios', 'cipherize', ('127.0.0.1', 2)),
  63. ('core.mods.ripv1', 'halcyonize', ('127.0.0.1', 2)),
  64. ]
  65. def run_with_timeout(fn, args, timeout=4):
  66. box = {"err": None}
  67. def target():
  68. try:
  69. fn(*args)
  70. except Exception as e:
  71. box["err"] = (type(e).__name__, str(e))
  72. t = threading.Thread(target=target, daemon=True)
  73. t.start()
  74. t.join(timeout)
  75. if t.is_alive():
  76. return "TIMEOUT", None
  77. return ("OK", None) if box["err"] is None else ("ERR", box["err"])
  78. for modname, fname, args in SPECS:
  79. mod = importlib.import_module(modname)
  80. fn = getattr(mod, fname, None)
  81. if fn is None:
  82. err.append(f"{modname}: missing function {fname}()")
  83. continue
  84. status, detail = run_with_timeout(fn, args, timeout=4)
  85. if status == "ERR":
  86. err.append(f"{modname}.{fname}{args} raised: {detail[0]}: {detail[1][:80]}")
  87. print(f" {modname:25s}.{fname:12s} {args} -> {status}")
  88. SPRAY_LIKE = [
  89. ('core.mods.spray', 'sprayize', ('127.0.0.1', 80, 1)),
  90. ('core.mods.smurf', 'smurfize', ('127.0.0.1', 80, 1)),
  91. ('core.mods.fraggle', 'fraggleize', ('127.0.0.1', 53, 1)),
  92. ]
  93. import os as _os
  94. _os_environ = dict(_os.environ)
  95. for modname, fname, args in SPRAY_LIKE:
  96. mod = importlib.import_module(modname)
  97. fn = getattr(mod, fname, None)
  98. if fn is None:
  99. err.append(f"{modname}: missing function {fname}()")
  100. continue
  101. status, detail = run_with_timeout(fn, args, timeout=4)
  102. if status == "ERR":
  103. msg = (detail[1] or "").lower()
  104. if "no such file" in msg or "open" in msg or "rpcs.txt" in msg or "snmp.txt" in msg or "ntp.txt" in msg:
  105. print(f" {modname:25s}.{fname:12s} {args} -> SKIP (no reflector file)")
  106. continue
  107. err.append(f"{modname}.{fname}{args} raised: {detail[0]}: {detail[1][:80]}")
  108. print(f" {modname:25s}.{fname:12s} {args} -> {status}")
  109. HTTP_MODS = [
  110. ('core.mods.rapidreset', 'RAPIDRESET', ()),
  111. ('core.mods.slowread', 'SLOWREAD', ()),
  112. ('core.mods.goldeneye', 'GOLDENEYE', ()),
  113. ]
  114. for modname, classname, _ in HTTP_MODS:
  115. try:
  116. mod = importlib.import_module(modname)
  117. cls = getattr(mod, classname, None)
  118. if cls is None:
  119. err.append(f"{modname}: missing class {classname}")
  120. else:
  121. print(f" {modname:25s}.{classname:12s} importable -> OK")
  122. except Exception as e:
  123. err.append(f"{modname} import failed: {type(e).__name__}: {e}")
  124. print(f"\nfake-send invocations: {calls}")
  125. for e in err:
  126. print("FAIL:", e)
  127. sys.exit(0 if not err else 1)