๐ŸŒ SQL Slammer โ€” '376๋ฐ”์ดํŠธ ํŒจํ‚ท ํ•œ ๊ฐœ'๊ฐ€ 10๋ถ„ ๋งŒ์— ์ „ ์„ธ๊ณ„๋ฅผ ๋ฉˆ์ถฐ ์„ธ์šด ์ดˆ๊ณ ์† ์›œ (2003)

2026-09-10 ยท Malware Deep-Dive

1. ๋ฐฐ๊ฒฝ/์—ญ์‚ฌ โ€” ์–ธ์ œ, ๋ˆ„๊ฐ€, ์™œ ์œ ๋ช…ํ•œ๊ฐ€

SQL ์Šฌ๋ž˜๋จธ(SQL Slammer)๋Š” 2003๋…„ 1์›” 25์ผ 05:30(UTC) ๋ฌด๋ ต, ๋งˆ์ดํฌ๋กœ์†Œํ”„ํŠธ SQL Server 2000 ยท MSDE 2000์˜ ์ทจ์•ฝ์ ์„ ๋…ธ๋ฆฌ๊ณ  ๋“ฑ์žฅํ•œ ์ž๊ธฐ๋ณต์ œํ˜• ์›œ์ด๋‹ค. ๋ณ„์นญ์œผ๋กœ ์‚ฌํŒŒ์ด์–ด(Sapphire), ํ—ฌ์ปจ(Helkern)์ด๋ผ๊ณ ๋„ ๋ถˆ๋ ธ๋‹ค. ์ œ์ž‘์ž๋Š” ์ง€๊ธˆ๊นŒ์ง€ ๋ฐํ˜€์ง€์ง€ ์•Š์•˜์ง€๋งŒ, ๊ทธ ๊ฒฐ๊ณผ๋งŒ์œผ๋กœ 2003๋…„ ์ตœ์•…์˜ ์ธํ„ฐ๋„ท ๋Œ€๋ž€์„ ์ผ์œผ์ผฐ๋‹ค.

2. ๊ฐ์—ผยท์ „ํŒŒ ๊ฒฝ๋กœ โ€” ์–ด๋–ป๊ฒŒ ํผ์กŒ๋‚˜

์Šฌ๋ž˜๋จธ์˜ ํ™•์‚ฐ์€ ์–ด์ง€๋Ÿฝ๊ฒŒ ๋‹จ์ˆœํ•˜๋‹ค. ์ทจ์•ฝํ•œ ์„œ๋น„์Šค์˜ UDP ํฌํŠธ๋กœ 'ํ•œ ๊ฐœ์˜ ํŒจํ‚ท'์„ ๋ณด๋‚ด๋ฉด ๊ฐ์—ผ๋˜๊ณ , ๊ฐ์—ผ๋œ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์Šค์Šค๋กœ ๊ฐ™์€ ํŒจํ‚ท์„ ์Ÿ์•„๋‚ธ๋‹ค. ๊ทธ๊ฒŒ ์ „๋ถ€๋‹ค.

3. ๋™์ž‘ ์›๋ฆฌ ์ƒ์„ธ ๋ถ„์„ โ€” ์ฝ”๋“œ/๊ตฌ์กฐ ๋ ˆ๋ฒจ์—์„œ

์Šฌ๋ž˜๋จธ๋Š” '์›œ ๋ณธ์ฒด + ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ทจ์•ฝ์ '์ด๋ผ๋Š” ๊ณ ์ „์  ๊ตฌ๋„๊ฐ€ ์•„๋‹ˆ๋ผ, '์ทจ์•ฝ์  ํ•˜๋‚˜ = ์›œ ํ•˜๋‚˜'๋ผ๋Š” ๊ทน๋‹จ์ ์œผ๋กœ ์••์ถ•๋œ ๊ตฌ์กฐ๋ฅผ ํƒํ–ˆ๋‹ค. ๊ทธ๋ž˜์„œ 376๋ฐ”์ดํŠธ ์•ˆ์— ์ „ํŒŒ์— ํ•„์š”ํ•œ ๋ชจ๋“  ๊ฒƒ์ด ๋“ค์–ด ์žˆ์—ˆ๋‹ค.

4. ํ”ผํ•ด ๊ทœ๋ชจ/์˜ํ–ฅ โ€” ์‹ค์ œ ์‚ฌ๋ก€ ์ˆ˜์น˜

5. PoC โ€” ๊ต์œก์šฉ ๋ชจ์˜ ์ฝ”๋“œ๋กœ ๋™์ž‘ ์›๋ฆฌ ์žฌํ˜„

โš ๏ธ ์•ˆ์ „ ๊ทœ์น™: ์•„๋ž˜ ์ฝ”๋“œ๋Š” ์‹ค์ œ ์Šฌ๋ž˜๋จธ ํŽ˜์ด๋กœ๋“œ(376๋ฐ”์ดํŠธ ์…ธ์ฝ”๋“œ)๋‚˜ CVE-2002-0649 ์ต์Šคํ”Œ๋กœ์ž‡ ์ฝ”๋“œ๊ฐ€ ์•„๋‹ˆ๋ผ, "๋™์ž‘ ์›๋ฆฌ๋งŒ ์žฌํ˜„ํ•œ ๊ต์œก์šฉ ๋ชจ์˜ ์ฝ”๋“œ"๋‹ค. ์‹ค์ œ ์•…์„ฑ์ฝ”๋“œ ๋ณต์‚ฌยท๋ฐฐํฌ, ์‹ค์ œ ๋„คํŠธ์›Œํฌ ์Šค์บ”ยท๊ณต๊ฒฉ์€ ์ผ์ ˆ ํฌํ•จํ•˜์ง€ ์•Š์œผ๋ฉฐ, ๊ณต๊ฒฉ ๋Œ€์ƒ์€ ํ•ญ์ƒ ๊ฐ€์ƒ์˜ ๋กœ์ปฌ ์‹ค์Šต ํ™˜๊ฒฝ(๋ฉ”๋ชจ๋ฆฌ ์† ๊ฐ€์ƒ ํ˜ธ์ŠคํŠธ / ๊ฐ€์ƒ ๋žฉ)์„ ์ „์ œ๋กœ ํ•œ๋‹ค. ์•„๋ž˜ ์ฝ”๋“œ๋Š” ์ด ๊ธ€ ์ž‘์„ฑ ์‹œ ์‹ค์ œ๋กœ ์‹คํ–‰ํ•ด ์ถœ๋ ฅ์„ ๊ทธ๋Œ€๋กœ ์˜ฎ๊ฒผ๋‹ค.

PoC 1 โ€” 'ํญ๋ฐœ์  ํ™•์‚ฐ ์†๋„' ์žฌํ˜„: ์Šฌ๋ž˜๋จธ์˜ ํ™•์‚ฐ ์—ญํ•™(๋ฌด์ž‘์œ„ ์Šค์บ” + ์ดˆ๊ธฐ 8.5์ดˆ๋งˆ๋‹ค 2๋ฐฐ)์„ ์ˆ˜์‹์œผ๋กœ ๋ชจ์˜ํ•œ๋‹ค. ์‚ฌ๋žŒ์ด ํŒจ์น˜๋ฅผ ๋ฐฐํฌํ•  ์‹œ๊ฐ„์กฐ์ฐจ ์ฃผ์ง€ ์•Š๋Š” ์†๋„๋ฅผ ๋ณด์—ฌ์ค€๋‹ค.

#!/usr/bin/env python3
"""
PoC 1 (๊ต์œก์šฉ) โ€” SQL Slammer(2003)์˜ 'ํญ๋ฐœ์  ํ™•์‚ฐ ์†๋„' ์žฌํ˜„ ๋ชจ์˜.

์‹ค์ œ ์ทจ์•ฝ์ /ํŒจํ‚ท/์Šค์บ๋„ˆ๊ฐ€ ์•„๋‹ˆ๋ผ, Slammer์˜ ํ™•์‚ฐ ์—ญํ•™์„ ์ˆ˜์‹์œผ๋กœ ์žฌํ˜„ํ•œ๋‹ค.
Slammer๋Š” UDP/1434๋กœ 'ํ•œ ๊ฐœ์˜ ํŒจํ‚ท'์„ ๋ณด๋‚ด ๊ฐ์—ผ์‹œํ‚ค๋Š” ๋žœ๋ค ์Šค์บ๋‹ ์›œ์ด์—ˆ๋‹ค.
- ์ฃผ์†Œ๊ณต๊ฐ„ 2^32 (IPv4 ์ „์ฒด)๋ฅผ ๋ฌด์ž‘์œ„๋กœ ์Šค์บ”
- ๊ฐ์—ผ ํ˜ธ์ŠคํŠธ๋‹น ์ดˆ๋‹น ์ˆ˜์ฒœ ๊ฐœ ํŒจํ‚ท
- ๊ฒฐ๊ณผ: ์ดˆ๊ธฐ 8.5์ดˆ๋งˆ๋‹ค ๊ฐ์—ผ ๋Œ€์ˆ˜ 2๋ฐฐ, 10๋ถ„ ๋‚ด ์ทจ์•ฝ ํ˜ธ์ŠคํŠธ ๋Œ€๋ถ€๋ถ„ ๊ฐ์—ผ

๋ชจ๋‘ '๊ฐ€์ƒ์˜ ํ˜ธ์ŠคํŠธ ๊ฐœ์ฒด'์— ๋Œ€ํ•œ ๊ณ„์‚ฐ์ด๋ฉฐ ์‹ค์ œ ๋„คํŠธ์›Œํฌ ํ˜ธ์ถœ์€ ์—†๋‹ค.
"""
import math

N = 75_000          # ์ „ ์„ธ๊ณ„ ์ทจ์•ฝ ํ˜ธ์ŠคํŠธ(๊ฐ€์ƒ) โ€” ๋„๋ฆฌ ์ธ์šฉ๋˜๋Š” ๊ฐ์—ผ ๊ทœ๋ชจ
A = 2 ** 32         # IPv4 ์ „์ฒด ์ฃผ์†Œ๊ณต๊ฐ„
DOUBLE = 8.5        # ์ดˆ๊ธฐ ๊ฐ์—ผ ๋Œ€์ˆ˜ 2๋ฐฐ ์ฃผ๊ธฐ(์ดˆ) โ€” ๋ฌธํ—Œ ๋ณด๊ณ ๊ฐ’
# ์ดˆ๊ธฐ 1๋Œ€๊ฐ€ 8.5์ดˆ๋งˆ๋‹ค 2๋ฐฐ๊ฐ€ ๋˜๋„๋ก ์Šค์บ”๋ฅ  ์‚ฐ์ •: rate = ln2/DOUBLE = scan*N/A
SCAN_PER_HOST = (math.log(2) / DOUBLE) * A / N       # ํ˜ธ์ŠคํŠธ๋‹น ์ดˆ๋‹น ์Šค์บ” ์ˆ˜
AGG_CAP = 55_000_000                                  # ๊ด€์ธก๋œ ์ตœ๋Œ€ ์ด ์Šค์บ”๋ฅ  55M/์ดˆ(๋Œ€์—ญํญ ํฌํ™”)

dt = 0.1
S = 1          # ๊ฐ์—ผ ๋Œ€์ˆ˜ (๋‹จ์ผ ์‹œ๋“œ)
t = 0.0
marks = {}
targets = [0.01, 0.10, 0.50, 0.90, 0.99]
prev = S
doubling_seen = []

while S < N * 0.999 and t < 3600:
    per_host = min(SCAN_PER_HOST, AGG_CAP / S)       # ํ˜ธ์ŠคํŠธ/๋„คํŠธ์›Œํฌ ๋Œ€์—ญํญ ์ƒํ•œ
    p_hit = (N - S) / A                              # ๋ฌด์ž‘์œ„ ์Šค์บ”์ด '์•„์ง ์•ˆ ๊ฑธ๋ฆฐ ์ทจ์•ฝ ํ˜ธ์ŠคํŠธ'๋ฅผ ๋งž์ถœ ํ™•๋ฅ 
    new = S * per_host * p_hit * dt
    S += new
    t += dt
    if prev > 0 and S >= 2 * prev:
        doubling_seen.append(round(t, 1)); prev = S
    for f in targets:
        if f not in marks and S >= N * f:
            marks[f] = round(t, 1)

print("=== SQL Slammer ํ™•์‚ฐ ๋ชจ์˜ (๋‹จ์ผ ์‹œ๋“œ, ์ทจ์•ฝ ํ˜ธ์ŠคํŠธ %d๋Œ€, ์ฃผ์†Œ๊ณต๊ฐ„ 2^32) ===" % N)
print("ํ˜ธ์ŠคํŠธ๋‹น ์ดˆ๋‹น ์Šค์บ”(์ดˆ๊ธฐ)            : %.0f packets/s" % SCAN_PER_HOST)
print("์ด ์Šค์บ” ๋Œ€์—ญํญ ์ƒํ•œ(ํฌํ™”)           : %s packets/s" % format(AGG_CAP, ','))
print("์ดˆ๊ธฐ ๊ฐ์—ผ ๋Œ€์ˆ˜ 2๋ฐฐ ์ฃผ๊ธฐ             : %.1f ์ดˆ" % DOUBLE)
print("-" * 60)
for f in targets:
    lbl = {0.01: "์ทจ์•ฝ ํ˜ธ์ŠคํŠธ 1% ๊ฐ์—ผ", 0.10: "10% ๊ฐ์—ผ", 0.50: "50% ๊ฐ์—ผ(์ค‘๊ฐ„๊ฐ’)",
           0.90: "90% ๊ฐ์—ผ", 0.99: "99% ๊ฐ์—ผ"}[f]
    print("%-28s : %6.1f ์ดˆ (%.2f ๋ถ„)" % (lbl, marks.get(f, -1), marks.get(f, -1) / 60))
print("-" * 60)
print("์ฒซ 3ํšŒ '2๋ฐฐ ์ฆ๊ฐ€'๊นŒ์ง€ ๊ฑธ๋ฆฐ ์‹œ๊ฐ„       :", doubling_seen[:3], "์ดˆ")
print("90%% ๊ฐ์—ผ๊นŒ์ง€ ๊ฑธ๋ฆฐ ์‹œ๊ฐ„              : %.1f ๋ถ„" % (marks[0.90] / 60))
print("\n๊ตํ›ˆ: ์ „ํŒŒ๊ฐ€ '๋ถ„ ๋‹จ์œ„'๋กœ ๋๋‚œ๋‹ค โ€” ์‚ฌ๋žŒ์ด ํŒจ์น˜๋ฅผ ๋ฐฐํฌํ•  ์‹œ๊ฐ„์ด ์—†๋‹ค.")
print("      ๋А๋ฆฐ(์‚ฌ๋žŒ) ๋Œ€์‘ vs ๋น ๋ฅธ(์›œ) ์ „ํŒŒ์˜ ์†๋„ ๊ฒฝ์Ÿ์—์„œ ์ž๋™ํ™”ยท๋„คํŠธ์›Œํฌ ์ฐจ๋‹จ๋งŒ์ด ์ด๊ธด๋‹ค.")

์‹คํ–‰ ์ถœ๋ ฅ:

=== SQL Slammer ํ™•์‚ฐ ๋ชจ์˜ (๋‹จ์ผ ์‹œ๋“œ, ์ทจ์•ฝ ํ˜ธ์ŠคํŠธ 75000๋Œ€, ์ฃผ์†Œ๊ณต๊ฐ„ 2^32) ===
ํ˜ธ์ŠคํŠธ๋‹น ์ดˆ๋‹น ์Šค์บ”(์ดˆ๊ธฐ)            : 4670 packets/s
์ด ์Šค์บ” ๋Œ€์—ญํญ ์ƒํ•œ(ํฌํ™”)           : 55,000,000 packets/s
์ดˆ๊ธฐ ๊ฐ์—ผ ๋Œ€์ˆ˜ 2๋ฐฐ ์ฃผ๊ธฐ             : 8.5 ์ดˆ
------------------------------------------------------------
์ทจ์•ฝ ํ˜ธ์ŠคํŠธ 1% ๊ฐ์—ผ                 :   81.7 ์ดˆ (1.36 ๋ถ„)
10% ๊ฐ์—ผ                       :  111.2 ์ดˆ (1.85 ๋ถ„)
50% ๊ฐ์—ผ(์ค‘๊ฐ„๊ฐ’)                  :  158.3 ์ดˆ (2.64 ๋ถ„)
90% ๊ฐ์—ผ                       :  283.9 ์ดˆ (4.73 ๋ถ„)
99% ๊ฐ์—ผ                       :  463.6 ์ดˆ (7.73 ๋ถ„)
------------------------------------------------------------
์ฒซ 3ํšŒ '2๋ฐฐ ์ฆ๊ฐ€'๊นŒ์ง€ ๊ฑธ๋ฆฐ ์‹œ๊ฐ„       : [8.6, 17.2, 25.8] ์ดˆ
90% ๊ฐ์—ผ๊นŒ์ง€ ๊ฑธ๋ฆฐ ์‹œ๊ฐ„              : 4.7 ๋ถ„

๊ตํ›ˆ: ์ „ํŒŒ๊ฐ€ '๋ถ„ ๋‹จ์œ„'๋กœ ๋๋‚œ๋‹ค โ€” ์‚ฌ๋žŒ์ด ํŒจ์น˜๋ฅผ ๋ฐฐํฌํ•  ์‹œ๊ฐ„์ด ์—†๋‹ค.
      ๋А๋ฆฐ(์‚ฌ๋žŒ) ๋Œ€์‘ vs ๋น ๋ฅธ(์›œ) ์ „ํŒŒ์˜ ์†๋„ ๊ฒฝ์Ÿ์—์„œ ์ž๋™ํ™”ยท๋„คํŠธ์›Œํฌ ์ฐจ๋‹จ๋งŒ์ด ์ด๊ธด๋‹ค.

PoC 2 โ€” 'ํŒŒ์ผ ์—†๋Š” ๋‹จ์ผ ํŒจํ‚ท ๋ฉ”๋ชจ๋ฆฌ ์›œ'๊ณผ ๊ฒฉ๋ฆฌ: ๋””์Šคํฌ์— ์•„๋ฌด๊ฒƒ๋„ ๋‚จ๊ธฐ์ง€ ์•Š๊ณ  ๋ฉ”๋ชจ๋ฆฌ์—์„œ๋งŒ ์‚ฌ๋Š” ์›œ์ด ๋„คํŠธ์›Œํฌ ๊ฒฝ๊ณ„ ํ†ต์ œ(UDP/1434 egress ์ฐจ๋‹จ + ์„ธ๊ทธ๋ฉ˜ํ…Œ์ด์…˜) ํ•œ ์ค„๋กœ ๋ฉˆ์ถ”๋Š” ๋ชจ์Šต์„ ๋Œ€๋น„ํ•ด ๋ณด์—ฌ์ค€๋‹ค.

#!/usr/bin/env python3
"""
PoC 2 (๊ต์œก์šฉ) โ€” 'ํŒŒ์ผ ์—†๋Š” ๋‹จ์ผ ํŒจํ‚ท ๋ฉ”๋ชจ๋ฆฌ ์›œ'์˜ ์ „ํŒŒ/๊ฒฉ๋ฆฌ ์žฌํ˜„ ๋ชจ์˜.

Slammer์˜ ๋‘ ๊ฐ€์ง€ ํŠน์ง•์„ ์•ˆ์ „ํ•˜๊ฒŒ ํ‰๋‚ด ๋‚ธ๋‹ค:
  (1) ๋””์Šคํฌ์— ํŒŒ์ผ์„ ๋งŒ๋“ค์ง€ ์•Š๋Š”๋‹ค โ€” ์ฝ”๋“œ๊ฐ€ sqlservr.exe '๋ฉ”๋ชจ๋ฆฌ ์•ˆ'์—์„œ๋งŒ ์‚ฐ๋‹ค.
      (๊ทธ๋ž˜์„œ ์žฌ๋ถ€ํŒ…๋งŒ์œผ๋กœ๋„ ํ”์ ์ด ์‚ฌ๋ผ์กŒ๋‹ค.)
  (2) 'ํ•œ ๊ฐœ์˜ ํŒจํ‚ท'์ด ๊ณง ์›œ ๋ณธ์ฒด + ๊ฐ์—ผ ์ฝ”๋“œ๋‹ค โ€” ๋ฐ›๋Š” ์ˆœ๊ฐ„ ๊ทธ ํ”„๋กœ์„ธ์Šค๊ฐ€
      ๋˜ ๋‹ค๋ฅธ ์ž„์˜ ํ˜ธ์ŠคํŠธ๋กœ ๊ฐ™์€ ํŒจํ‚ท์„ ๊ณ„์† ์žฌ์ „์†กํ•˜๋ฉฐ ์Šค์Šค๋กœ ๋ณต์ œ๋œ๋‹ค.

์—ฌ๊ธฐ์„œ๋Š” ์‹ค์ œ ์†Œ์ผ“/ํŒจํ‚ท์„ ์ „ํ˜€ ์“ฐ์ง€ ์•Š๋Š”๋‹ค. '๋„คํŠธ์›Œํฌ'์™€ 'ํ˜ธ์ŠคํŠธ'๋Š” ๋ชจ๋‘
๋ฉ”๋ชจ๋ฆฌ ์•ˆ์˜ ๊ฐ€์ƒ ๊ฐ์ฒด์ด๋ฉฐ, ๊ณต๊ฒฉ ๋Œ€์ƒ์€ ๊ฐ€์ƒ์˜ ๋กœ์ปฌ ์‹ค์Šต ๋žฉ(10.0.0.0/24)์ด๋‹ค.
"""
import os, random

random.seed(20030125)  # 2003-01-25 (Slammer ๋ฐœ์ƒ์ผ)

VIRTUAL_WORM = b"SLAM" * 94   # 376๋ฐ”์ดํŠธ ํŒจํ‚ท์„ ์ƒ์ง•ํ•˜๋Š” ์ž๋ฆฌํ‘œ์‹œ์ž(์‹ค์ œ ํŽ˜์ด๋กœ๋“œ ์•„๋‹˜)
SCAN_BURST = 30               # ๊ฐ์—ผ 1๋Œ€๊ฐ€ ๋ฟœ๋Š” ์Šค์บ” ํŒจํ‚ท ์ˆ˜(๋†’์€ ์Šค์บ”๋ฅ ์„ ์ƒ์ง•)


class FakeHost:
    """๊ฐ€์ƒ์˜ ๋กœ์ปฌ ์‹ค์Šต ํ˜ธ์ŠคํŠธ. ์ทจ์•ฝ ์„œ๋น„์Šค(UDP:1434)๊ฐ€ ๋–  ์žˆ๋‹ค๊ณ  ๊ฐ€์ •."""
    def __init__(self, ip):
        self.ip = ip
        self.infected = False
        self.mem_payload = None   # ๋ฉ”๋ชจ๋ฆฌ ์ƒ์ฃผ ์›œ(๋””์Šคํฌ ์•„๋‹˜)
        self.emitted = 0          # ์ด ํ˜ธ์ŠคํŠธ๊ฐ€ ๋ฐ–์œผ๋กœ ๋ณด๋‚ธ ํŒจํ‚ท ์ˆ˜

    def service_1434(self, datagram, lab, egress_blocked):
        """์ทจ์•ฝ ์„œ๋น„์Šค๊ฐ€ ํŒจํ‚ท์„ ๋ฐ›์œผ๋ฉด '๊ฒฝ๊ณ„๊ฒ€์‚ฌ ์—†์ด' ๊ทธ๋Œ€๋กœ ์‹คํ–‰/์ „ํŒŒํ•œ๋‹ค๊ณ  ๊ฐ€์ •."""
        if datagram == VIRTUAL_WORM and not self.infected:
            self.infected = True
            self.mem_payload = datagram           # ํŒŒ์ผ๋กœ ์ €์žฅํ•˜์ง€ ์•Š์Œ โ†’ ๋ฉ”๋ชจ๋ฆฌ ์ „์šฉ
            self.spread(lab, egress_blocked)

    def spread(self, lab, egress_blocked):
        """๊ฐ์—ผ ์ฆ‰์‹œ ๋ฌด์ž‘์œ„ ํ˜ธ์ŠคํŠธ๋กœ '๊ฐ™์€ ํŒจํ‚ท'์„ ์—ฌ๋Ÿฌ ๊ฐœ ๋ณด๋‚ธ๋‹ค(์Šค์บ” ํญ์ฃผ)."""
        if egress_blocked:
            return                                # ์„ธ๊ทธ๋ฉ˜ํ…Œ์ด์…˜/egress ํ•„ํ„ฐ๊ฐ€ ๋ง‰์œผ๋ฉด ํ™•์‚ฐ ์ •์ง€
        for _ in range(SCAN_BURST):
            candidates = [h for h in lab if not h.infected]
            if not candidates:
                return
            target = random.choice(candidates)
            self.emitted += 1
            target.service_1434(self.mem_payload, lab, egress_blocked)


def run_scenario(egress_blocked):
    lab = [FakeHost("10.0.0.%d" % i) for i in (11, 12, 13, 14, 15, 16, 17, 18)]
    lab[0].service_1434(VIRTUAL_WORM, lab, egress_blocked)   # ์ตœ์ดˆ 1๊ฐœ ํŒจํ‚ท์ด ์‹œ๋“œ
    infected = [h.ip for h in lab if h.infected]
    packets = sum(h.emitted for h in lab)
    return infected, packets


print("=== ๊ฐ€์ƒ ๋กœ์ปฌ ๋žฉ(10.0.0.0/24, ํ˜ธ์ŠคํŠธ 8๋Œ€, UDP/1434 ์ทจ์•ฝ) ===")
print("์›œ ๋ณธ์ฒด(๊ฐ€์ƒ ํŽ˜์ด๋กœ๋“œ) ๊ธธ์ด: %d bytes (์‹ค์ œ ์•…์„ฑ์ฝ”๋“œ ์•„๋‹˜, ์ž๋ฆฌํ‘œ์‹œ์ž)\n" % len(VIRTUAL_WORM))

for mode, blocked in [("A. ๊ฒฉ๋ฆฌ/ํ•„ํ„ฐ ์—†์Œ", False),
                      ("B. UDP/1434 egress ์ฐจ๋‹จ + ์„ธ๊ทธ๋ฉ˜ํ…Œ์ด์…˜", True)]:
    infected, packets = run_scenario(blocked)
    print("[%s]" % mode)
    print("  ๊ฐ์—ผ ํ˜ธ์ŠคํŠธ : %d / 8  -> %s" % (len(infected), infected))
    print("  ๋ฐœ์ƒ ํŒจํ‚ท   : %d ๊ฐœ" % packets)
    print("  ๋””์Šคํฌ ํŒŒ์ผ : ์—†์Œ (๋ฉ”๋ชจ๋ฆฌ ์ „์šฉ ์›œ โ†’ ์žฌ๋ถ€ํŒ… ์‹œ ์†Œ๋ฉธ)")
    print()

# ๋””์Šคํฌ ํ”์ ์ด ์ •๋ง '์—†์Œ'์ธ์ง€ ์‹ค์ œ๋กœ ํ™•์ธ (์‹ค์Šต ๋””๋ ‰ํ„ฐ๋ฆฌ์— ์›œ ํŒŒ์ผ์ด ์•ˆ ์ƒ๊ฒผ๋Š”์ง€)
dropped = [f for f in os.listdir('.')
           if f.lower().startswith(('sqlexp', 'helkern', 'msworm'))]
print("์‹ค์Šต ๋””๋ ‰ํ„ฐ๋ฆฌ์—์„œ ๋ฐœ๊ฒฌ๋œ ์›œ ํŒŒ์ผ:", dropped if dropped else "์—†์Œ (์˜ˆ์ƒ๋Œ€๋กœ ๋””์Šคํฌ ๋ฌดํ”์ )")
print("\n๊ตํ›ˆ: ๋„คํŠธ์›Œํฌ ๊ฒฝ๊ณ„ ํ†ต์ œ(1434 egress ์ฐจ๋‹จ + ์„ธ๊ทธ๋ฉ˜ํ…Œ์ด์…˜)๋งŒ์ด")
print("      '๋ฉ”๋ชจ๋ฆฌ ์ „์šฉยท๋‹จ์ผ ํŒจํ‚ท' ์›œ์˜ ํ™•์‚ฐ์„ ์ฆ‰์‹œ ๋Š๋Š”๋‹ค. ํ˜ธ์ŠคํŠธ ๋ฐฑ์‹ ๋งŒ์œผ๋ก  ๋Šฆ๋‹ค.")

์‹คํ–‰ ์ถœ๋ ฅ:

=== ๊ฐ€์ƒ ๋กœ์ปฌ ๋žฉ(10.0.0.0/24, ํ˜ธ์ŠคํŠธ 8๋Œ€, UDP/1434 ์ทจ์•ฝ) ===
์›œ ๋ณธ์ฒด(๊ฐ€์ƒ ํŽ˜์ด๋กœ๋“œ) ๊ธธ์ด: 376 bytes (์‹ค์ œ ์•…์„ฑ์ฝ”๋“œ ์•„๋‹˜, ์ž๋ฆฌํ‘œ์‹œ์ž)

[A. ๊ฒฉ๋ฆฌ/ํ•„ํ„ฐ ์—†์Œ]
  ๊ฐ์—ผ ํ˜ธ์ŠคํŠธ : 8 / 8  -> ['10.0.0.11', '10.0.0.12', '10.0.0.13', '10.0.0.14', '10.0.0.15', '10.0.0.16', '10.0.0.17', '10.0.0.18']
  ๋ฐœ์ƒ ํŒจํ‚ท   : 7 ๊ฐœ
  ๋””์Šคํฌ ํŒŒ์ผ : ์—†์Œ (๋ฉ”๋ชจ๋ฆฌ ์ „์šฉ ์›œ โ†’ ์žฌ๋ถ€ํŒ… ์‹œ ์†Œ๋ฉธ)

[B. UDP/1434 egress ์ฐจ๋‹จ + ์„ธ๊ทธ๋ฉ˜ํ…Œ์ด์…˜]
  ๊ฐ์—ผ ํ˜ธ์ŠคํŠธ : 1 / 8  -> ['10.0.0.11']
  ๋ฐœ์ƒ ํŒจํ‚ท   : 0 ๊ฐœ
  ๋””์Šคํฌ ํŒŒ์ผ : ์—†์Œ (๋ฉ”๋ชจ๋ฆฌ ์ „์šฉ ์›œ โ†’ ์žฌ๋ถ€ํŒ… ์‹œ ์†Œ๋ฉธ)

์‹ค์Šต ๋””๋ ‰ํ„ฐ๋ฆฌ์—์„œ ๋ฐœ๊ฒฌ๋œ ์›œ ํŒŒ์ผ: ์—†์Œ (์˜ˆ์ƒ๋Œ€๋กœ ๋””์Šคํฌ ๋ฌดํ”์ )

๊ตํ›ˆ: ๋„คํŠธ์›Œํฌ ๊ฒฝ๊ณ„ ํ†ต์ œ(1434 egress ์ฐจ๋‹จ + ์„ธ๊ทธ๋ฉ˜ํ…Œ์ด์…˜)๋งŒ์ด
      '๋ฉ”๋ชจ๋ฆฌ ์ „์šฉยท๋‹จ์ผ ํŒจํ‚ท' ์›œ์˜ ํ™•์‚ฐ์„ ์ฆ‰์‹œ ๋Š๋Š”๋‹ค. ํ˜ธ์ŠคํŠธ ๋ฐฑ์‹ ๋งŒ์œผ๋ก  ๋Šฆ๋‹ค.

6. ๋ฐฉ์–ด ๋ฐฉ๋ฒ•/๊ตํ›ˆ โ€” ์–ด๋–ป๊ฒŒ ๋ง‰์•˜๊ณ , ๋ฌด์—‡์„ ๋ฐฐ์šฐ๋‚˜

์ถœ์ฒ˜

ํ•จ๊ป˜ ์ฝ๊ธฐ: ๐Ÿ› Morris Worm (1988) โ€” ์ตœ์ดˆ์˜ ์ธํ„ฐ๋„ท ์›œ ยท ๐Ÿชฑ Conficker (2008) โ€” SMB ์›œ์˜ ์ •์  ยท ๐Ÿ’€ WannaCry (2017) โ€” EternalBlue๋กœ ์ „ ์„ธ๊ณ„๋ฅผ ๊ฐ•ํƒ€ํ•œ ์›œ

๋ชฉ๋ก์œผ๋กœ ๋Œ์•„๊ฐ€๊ธฐ