리눅스는 인터프리터다

2 hours ago 1
  • initrd를 커널이 직접 해석하고 실행하는 프로그램 단위로 정의하며, Linux를 일종의 인터프리터로 재해석함
  • kexec, base64, cpio를 이용해 자기 자신을 재부팅하는 재귀형 Linux 배포판을 구성, initrd가 스스로를 다시 실행함
  • /init 스크립트가 자신의 cpio 이미지를 출력하도록 하면 Quine 형태의 자기 복제 initrd가 형성됨
  • ELF 실행 구조와 ld.so, binfmt_misc를 통해 인터프리터 계층이 커널까지 이어지는 구조를 설명함
  • kexec나 QEMU를 활용하면 Linux 위에서 또 다른 Linux를 꼬리 재귀적으로 실행할 수 있어, 커널·가상화·인터프리터의 경계를 실험적으로 확장함

rkx.gz 역공학과 자기 재귀형 initrd 구조

  • curl https://astrid.tech/rkx.gz | gunzip | sudo sh 명령은 20MB 크기의 base64 인코딩된 셸 스크립트를 다운로드하고 실행함
    • 스크립트는 root 권한을 확인하고 kexec, base64, cpio의 존재를 검사
    • base64 데이터를 디코딩해 r이라는 cpio 아카이브를 만들고, 그 안에서 k라는 커널 이미지를 추출
    • kexec를 이용해 k를 커널로, r을 램디스크로 로드 후 실행
  • r.cpio 내부에는 /bin, /init, k 파일이 포함되며, k는 Linux 6.18.18 커널 이미지, /init은 셸 스크립트 형태
    • /init은 /proc을 마운트하고, /r에 현재 파일 시스템을 cpio로 묶은 뒤 kexec로 /k와 /r을 다시 실행
    • 결과적으로 자기 자신을 계속 재부팅하는 재귀형 Linux 배포판이 됨

Linux 커널을 인터프리터로 보는 관점

  • initrd는 단순한 부팅용 램디스크가 아니라, Linux 커널이 해석하고 실행하는 프로그램으로 볼 수 있음
    • curl | sh나 python3 script.py처럼 initrd도 커널에 의해 실행되는 입력 프로그램 형태
    • 따라서 Linux 커널은 initrd를 해석하는 인터프리터로 기능
  • 이 구조는 꼬리 재귀 최적화(tail-call optimization) 와 유사함
    • kexec는 이전 커널을 덮어쓰지 않고 새로운 메모리 공간에 로드해 실행
    • 각 커널은 이전 상태를 유지하지 않으며, 새로운 “스택 프레임”으로 교체됨

Quine과 initrd 자기 복제

  • Quine은 자기 자신을 출력하는 프로그램을 의미
    • /init 스크립트가 마지막에 cat /r을 수행하도록 하면 자신과 동일한 cpio를 출력
    • 이 경우 Linux initrd 인터프리터의 Quine이 형성됨
    • 모든 파일이 RAM 상의 tmpfs에 존재하므로 실제 디스크 I/O는 발생하지 않음

ELF, ld.so, 그리고 인터프리터의 계층

  • ELF 실행 파일은 헤더에 인터프리터(ld-linux-x86-64.so.2) 경로를 포함함
    • 실행 시 커널은 ld.so를 먼저 실행하고, ld.so가 ELF의 동적 라이브러리를 로드 후 프로그램을 실행
    • 따라서 ELF도 일종의 인터프리터 언어로 볼 수 있음
  • /bin/sh는 ld.so에 의해 해석되고, ld.so는 커널이 직접 해석
    • ld.so는 정적 링크된 ELF이므로 커널이 직접 실행 가능
    • 이로써 인터프리터 계층의 기저(base case) 가 형성됨

binfmt_misc를 통한 CPIO 실행

  • binfmt_misc를 이용하면 특정 매직 바이트를 가진 파일을 지정된 인터프리터로 실행 가능
    • 예시 등록 명령: echo ':cpio:M::\x30\x37\x30\x37\x30\x31::/path/to/my/script.sh:' > /proc/sys/fs/binfmt_misc/register
    • 이 설정으로 chmod +x된 CPIO 파일을 직접 실행 가능
  • QEMU를 이용해 CPIO를 initrd로 실행하는 스크립트를 인터프리터로 등록할 수 있음
    • QEMU는 지정된 커널과 initrd를 사용해 가상 머신을 부팅
    • 결과적으로 CPIO 파일의 인터프리터는 QEMU가 구동하는 Linux 커널이 됨

재귀적 인터프리터와 “가장 이상한 루프”

  • QEMU 기반 인터프리터는 새로운 Linux 환경 스택 프레임을 생성
    • Linux 위에서 또 다른 Linux를 실행하는 구조로, 메모리 한계까지 중첩 가능
    • kexec 기반 인터프리터로 대체하면 꼬리 호출 최적화된 재귀형 Linux 실행이 가능
  • /init에서 binfmt_misc를 등록하고 /r을 실행하도록 구성하면 자기 자신을 실행하는 initrd가 완성됨
    • /r은 CPIO 포맷의 다음 init 프로세스이며, 실행 시 다시 자신을 해석

결론

  • initrd는 단순한 부팅 도구가 아니라, Linux 커널이 해석하는 프로그램 단위
  • kexec와 binfmt_misc를 이용하면 Linux 자체를 인터프리터처럼 재귀적으로 실행 가능
  • 이 구조는 커널, 가상화, 인터프리터, 자기 복제 프로그램의 경계를 허무는 실험적 개념
  • 관련 소스코드는 GitHub 저장소 ifd3f/rekexec에 공개됨
Read Entire Article