
NVRAM 부팅 옵션을 통해 부팅 전 네트워크 임플란트를 설치하고, UKI를 체인로드하며, dracut 페이로드를 실행한 뒤 스톡 커널로 kexec하는 UEFI GRUB2 부트킷
slot2: AWS EC2 UEFI x86_64의 Amazon Linux 2023에서 OS 부팅 전 네트워크 임플란트를 지속시키는 2단계 UEFI GRUB2 부트킷
작성자: cenobyte [email protected] 2026
https://github.com/cenobyte-vincit/slot2
slot2는 EC2의 Amazon Linux 2023용 부트킷입니다. AWS EC2 UEFI 펌웨어가 이를 먼저 로드합니다. 내장된 임플란트는 기본 OS가 부팅되기 전에 부트킷 UKI(Unified Kernel Image: 부트킷 커널과 initrd를 포함하는 하나의 EFI 파일)에서 네트워크를 포함하여 실행된 다음, kexec를 사용하여 일반 부팅에서 사용했을 기본 커널을 시작합니다. 부팅되는 운영 체제는 실제 기본 운영 체제입니다.
지속성은 UEFI NVRAM 로드 옵션과 두 개의 파일(부트킷 ESP 파일과 부트킷 UKI)을 통해 이루어집니다. 사용자 공간 헬퍼/루트킷 서비스는 사용/요구되지 않으며, 벤더 부트로더를 교체하지도 않습니다. slot2에서 98-payload.sh는 부팅 전 C2/침투/유출과 대상 파일시스템에 RAT 또는 커널 기반 루트킷과 같은 페이로드를 삽입하기 위한 임의 디스크 쓰기에 사용되는 임플란트입니다. 이 트리의 임플란트는 데모용입니다. /root/HELLO.TXT를 쓰고 네트워크를 활성화하여 인터넷/네트워크 연결을 설정하며, 실제 작전에서는 네트워크 침투 또는 유출이 될 수 있습니다.
UEFI 펌웨어는 자체적으로 커널을 선택하지 않습니다. NVRAM 로드 옵션의 BootOrder를 순회하며, 각 옵션은 ESP의 EFI 실행 파일 하나를 가리키는 번호가 매겨진 슬롯(Boot0001, Boot0002, ...)입니다. EC2에서 Boot0001은 항상 존재합니다. 기본 \EFI\BOOT\BOOTX64.EFI를 시작하는 Amazon EBS 항목입니다. slot2는 같은 ESP의 두 번째 파일을 가리키는 Boot0002를 추가하고 BootOrder에서 Boot0002를 첫 번째로 설정합니다. 펌웨어는 여전히 Boot0001을 폴백으로 유지합니다.
두 번째 파일은 펌웨어가 실행할 수 있는 것이어야 하며, 펌웨어가 볼 수 없는 루트 파일시스템의 부트킷 UKI에 도달할 수 있어야 합니다. GRUB은 GPT와 XFS를 읽고 UKI를 찾아 체인로드할 수 있기 때문에 사용됩니다. 이미지는 패키지된 Amazon GRUB이 아닌, grub2-mkimage로 생성한 사용자 지정 이미지입니다. 기본 BOOTX64.EFI는 벤더가 둔 위치에 그대로 남아 있습니다. 여기서 GRUB의 유일한 역할은 UKI로 핸드오프하는 것입니다.
그런 다음 UKI 커널이 98-payload.sh를 실행하고, 99-kexec-stock.sh가 kexec를 사용하여 일반 BLS 부팅이 사용했을 기본 커널과 initrd를 시작합니다.
EC2 UEFI NVRAM
├── Boot0001 -> stock \EFI\BOOT\BOOTX64.EFI (untouched)
└── Boot0002 -> bootkit \EFI\BOOT\.BOOTX64.EFI (created; first on BootOrder)
|
v
ESP (VFAT) /boot/efi
└── /EFI/BOOT/
├── BOOTX64.EFI stock (untouched) <- Boot0001
└── .BOOTX64.EFI bootkit GRUB2 PE --chainload--+ <- Boot0002
|
root FS (XFS, typical AL2023) |
└── /var/lib/systemd/boot/ |
└── uki.efi <------------------------------------------+
|
| 98-payload.sh, then 99-kexec-stock.sh
| resolve stock target under /sysroot/boot/:
| loader/entries/*.conf (BLS + grubenv; AL2023 primary)
| grub2/grub.cfg (legacy fallback)
|
+-- kexec ----------------------------------------+
|
/boot (stock, untouched) |
├── vmlinuz-* <--------------------------------------------+
└── initramfs-*.img
|
+-- stock initrd -> stage-2 stock userspace
kexec가 실패하면 스테이지 1이 UKI 커널에서 계속 실행됩니다. 시스템은 부팅 가능한 상태를 유지합니다.
임플란트는 부트킷 UKI 내부의 dracut pre-pivot 훅인 98-payload.sh입니다. 부팅 후 사용자 공간 서비스가 아닙니다. 이 트리의 구현은 데모입니다. /sysroot를 읽기-쓰기로 다시 마운트하고, /root/HELLO.TXT를 쓰고, NIC를 활성화하고, DHCP를 수행한 다음 ifconfig.me를 wget합니다(5초 예산). 네트워크 실패는 kexec를 차단하지 않습니다.
스테이지 1은 /sysroot(일반적으로 XFS, rw로 다시 마운트됨)에 실제 루트를 둡니다. /boot는 /sysroot/boot입니다. 추가 EBS 볼륨은 훅이 마운트하지 않는 한 마운트되지 않습니다. 슬림 initrd에는 busybox udhcpc와 wget이 포함됩니다. ip(8)는 initrd 로더를 통해 실행되는 실제 루트 바이너리입니다.
런타임 호스트는 대상(deploy를 실행한 다음 부트킷으로 재부팅하는 EC2 인스턴스)입니다.
uefi 또는 uefi-preferred인 UEFI를 지원하는 EC2 인스턴스/boot/efi에 마운트된 ESP(systemd 자동 마운트도 무방함; deploy가 이를 트리거함)libefivar 및 libefiboot(deploy는 동적으로 링크됨; 둘 다 기본 OS에 포함되어 있음)ARM64 / Graviton은 테스트되지 않았으므로 (아직?) 지원되지 않습니다.
Amazon Linux 2023 x86_64.
./install-dependencies.sh 실행을 위한 루트 권한/boot/vmlinuz-$(uname -r) 및 /boot/initramfs-$(uname -r).img (이 파일들은 UKI에 패킹됨)cc, make, pkg-config, grub2-mkimage, objcopy, kexec, openssl, xxd./install-dependencies.sh는 부트스트랩입니다. 위의 dnf 패키지(추가로 grub2-efi-x64-modules, systemd-boot-unsigned, efivar-devel, dracut)를 설치하고 고정된 busybox udhcpc 및 wget 바이너리를 내려받습니다.
빌드 호스트에서:
./install-dependencies.sh
make
인자 없는 make는 uki.efi, BOOTX64.EFI, deploy를 생성합니다. ESP, /var/lib/systemd/boot 또는 NVRAM에는 쓰지 않습니다. 트레일러 매직과 SOURCE_DATE_EPOCH는 ARCHITECTURE.md에 있습니다.
동봉된 deploy ELF를 대상에 복사하십시오. 컴파일러가 필요 없습니다. uki.efi와 BOOTX64.EFI는 이미 트레일러 안에 있습니다.
scp deploy user@target-host:~/
동일 위치(colocated) AL2023 인스턴스에서는 복사가 선택 사항입니다. 빌드 트리에서 ./deploy를 실행하십시오.
다음 재부팅 시 펌웨어 Boot0002가 ESP PE를 로드하고, PE가 UKI를 체인로드하며, 페이로드가 실행된 다음 kexec가 기본 BLS 커널을 시작합니다(ARCHITECTURE.md). deploy가 EFI variables are not supported on this system을 출력하면 이 부팅은 BIOS입니다. Requirements를 참조하십시오.
deploy는 루트 권한이 필요합니다. 인자 없이 실행하면 트레일러 오프셋과 NVRAM을 덤프하고 아무것도 쓰지 않습니다. -y는 이미지와 NVRAM 항목을 설치한 다음 이 실행 파일을 완전 삭제하고 연결을 해제합니다. 그 외의 인자는 사용법을 출력합니다.
./deploy # dump only: trailer offsets and NVRAM; no writes
./deploy -y # plant, then wipe and unlink this binary
reboot
-y 실행이 성공하면 프로세스는 종료 후 자신의 실행 파일을 완전 삭제(/dev/urandom, truncate, unlink)하도록 예약하므로 ls deploy는 실패해야 합니다. 설치된 UKI와 부트킷 GRUB 이미지는 유지됩니다.
-y는 /var/lib/systemd/boot/uki.efi(root:root, 0500)와 /boot/efi/EFI/BOOT/.BOOTX64.EFI(root:root, VFAT에서 best-effort 0700)를 쓰고 NVRAM Boot0002를 생성한 다음 BootOrder에서 첫 번째로 설정합니다. 기본 BOOTX64.EFI는 Boot0001로 유지됩니다.
make
이것은 세 가지 산출물을 빌드합니다. 트리 내 테스트 스위트는 없습니다. 나중에 ./deploy -y를 실행할 AL2023 인스턴스에서 동일 위치의 make를 실행하는 것은 깨끗한 런타임 환경에 대한 증명이 아닙니다.
재부팅 후에는 스테이지 2 기본 사용자 공간에 있어야 합니다. 즉, 일반 BLS 부팅이 사용했을 커널, /proc/cmdline, initrd 경로입니다.
cat /root/HELLO.TXT
# expect: stage-1 cmdline with BOOTKIT_MARKER, 98-payload.sh banner,
# pre-OS network breadcrumbs (NIC up, DHCP/udhcpc, default route),
# wget / external_ip=... / result, then
# 99-kexec-stock: resolve=bls:..., kexec -l ok, kexec -e
grep BOOTKIT_MARKER /proc/cmdline || echo "no marker (stage-2 ok)"
# expect: no marker
dmesg | head -3
# expect: stock-style cmdline (BLS options), not BOOTKIT_MARKER=1
uname -r
# expect: the dnf/grubby default on disk
deploy -y는 아래의 기본값들을 씁니다. NVRAM BootOrder와 Boot0002는 파일이 아닌 펌웨어 상태입니다.
ESP PE 이름이나 UKI 경로를 변경하는 경우 mk-bootx64-efi.sh, deploy.c 및 NVRAM 항목을 동기화된 상태로 유지하십시오(ARCHITECTURE.md 참조).
amzn / 2023)과 EC2 형태의 Boot0001로 제한됩니다. 내장 PE 검사는 AMD64(0x8664)가 필요합니다. ARM64 / Graviton은 (아직?) 지원되지 않습니다.open 필터링은 이 프로젝트의 범위 밖입니다.deploy 자체 완전 삭제는 best-effort입니다. SSD나 NVMe에서의 보안 삭제(secure erase)가 아닙니다. 완전한 무기화와 더 높은 수준의 OPSEC를 위해서는 사용자 지정 deploy를 권장합니다.c5a.xlarge 및 t3.nano에서 개발 및 테스트되었습니다.| 경로 | 역할 |
|---|
/var/lib/systemd/boot/uki.efi | 스테이지 1 UKI(커널, 부트킷 initrd, cmdline) |
/boot/efi/EFI/BOOT/.BOOTX64.EFI | 부트킷 GRUB2 PE; 펌웨어 Boot0002가 이를 로드함 |
/boot/efi/EFI/BOOT/BOOTX64.EFI | 기본 PE(변경 없음); Boot0001 폴백 |
/boot/vmlinuz-*, /boot/initramfs-*.img, /boot/loader/entries/ | 기본 커널, initrd 및 BLS; kexec가 로드하는 것 |