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

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

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

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

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
macos_app_structure — macOS 앱 번들, plist 파일 및 launchd 프로세스 동작에 대한 교육용 심층 분석으로, 페이로드를 .app 파일로 패키징하고 프로세스 트리 모니터링을 회피하는 공격적 보안 노트를 포함합니다. | Kitploit
도구/GitHubGitHub/yo-yo-yo-jbo/macos_app_structure
Persistence MechanismsIDS/IPS EvasionLearning & EducationRed TeamingPayload Development
GitHubyo-yo-yo-jbo/macos_app_structure

macos_app_structure

macOS 앱 번들, plist 파일 및 launchd 프로세스 동작에 대한 교육용 심층 분석으로, 페이로드를 .app 파일로 패키징하고 프로세스 트리 모니터링을 회피하는 공격적 보안 노트를 포함합니다.

저장소 보기
47261개월 전Kitploit 검토 완료

인기

모두 보기 →

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

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

macOS 소개 - macOS 앱 구조

Linux나 Windows에서 macOS로 전환하는 것은 낯선 새 땅을 걷는 것처럼 느껴질 수 있습니다. Linux는 오픈소스이고 Windows는 문서화가 잘 되어 있고 매우 인기가 있지만(macOS는 정확히 그 둘 다 아닙니다), macOS는 때때로 도전적으로 느껴질 수 있습니다. 이 블로그 게시물에서는 macOS에서 처음으로 눈에 띌 수 있는 몇 가지 것들 - 앱, 어디에나 있는 앱! - 에 대해 논의하려고 합니다.

앱 vs. 프로세스 (태스크?)

Windows나 Linux 배경에서 온 경우, 앱이라는 개념이 이상하게 보일 수 있습니다. 우리 모두 스레드가 "실행 단위"이고 프로세스는 고유한 주소 공간을 가진 스레드의 컨테이너라는 것을 알고 있습니다. 그 이상이 뭐가 있을까요? 음, 프로세스는 단일 파일로 배포되는 경우가 거의 없습니다. Windows와 Linux 모두에서 코드가 작동하는 데 필요한 많은 것들이 있으며, 그중 일부는 다음과 같습니다:

  • 로드 가능한 모듈(.dll, .so). 예를 들어, C 런타임 라이브러리(Windows의 msvcr<version>.dll, libc-<version>.so) 및 기타 의존성.
  • 리소스. 예를 들어, Windows에서 실행 파일은 PE라는 형식으로 제공되며 디렉터리를 가지고 있습니다. 그중 하나는 리소스 디렉터리로, 리소스(이미지, 문자열 등)를 포함할 수 있습니다(여기에 어느 정도 문서화되어 있습니다). 물론 리소스는 디스크에서 동적으로 로드될 수도 있습니다.
  • 디지털 서명. Linux에서는 덜 일반적이지만(일부 형태로는 존재합니다 - 예를 들어, Debian 패키지에서), 중요합니다. Windows에서는 PE 파일 자체(여기 참조) 또는 카탈로그 파일(즉, 외부)에 존재할 수 있습니다.
  • 구성. Linux에서는 파일(신뢰할 수 있는 .bashrc 파일 등)이고, Windows에서는 파일(예: xml, ini, json)과 Windows 레지스트리로 나뉩니다.
  • 기타 실행 파일.

음, macOS는 앱 번들(Application Bundles)에 큰 중점을 둡니다. 그 아이디어는 프로그램 실행에 필요한 (거의) 모든 것 - 리소스, 지역화 정보 등 - 을 디렉터리 구조에 패키징하는 것입니다. 물론 모든 것을 깔끔하게 패키징할 수 있는 것은 아닙니다(예를 들어 C 런타임 라이브러리). 하지만 그럼에도 불구하고 모든 것이 함께 번들되어 있다는 것을 의미합니다. 거대한 레지스트리를 탐색하거나 난해한 구성 파일 위치를 찾기 위해 매뉴얼 페이지를 읽을 필요가 없습니다. 앱 번들은 단지 .app으로 끝나는 디렉터리입니다. UI가 .app 확장자(그리고 그것이 디렉터리라는 사실)를 숨기긴 하지만요. 공격자의 관점에서 이것은 흥미롭습니다. Application Bundle은 임의의 아이콘을 가질 수 있고 .app 확장자를 숨기기 때문에, 악성코드 전달은 의심하지 않는 사용자가 그런 앱을 클릭하도록 속임으로써 이루어질 수 있습니다. 예를 들어, PDF 아이콘이 있는 Resume.app 파일을 생각해 보세요.

Application Bundle의 디렉터리 구조는 내장된 Calculator 앱으로 쉽게 살펴볼 수 있습니다:

root@kitploit:~
jbo@McJbo ~ % cd /System/Applications/Calculator.app
jbo@McJbo Calculator.app % ll
total 0
drwxr-xr-x   3 root  wheel    96 Mar 17 21:34 .
drwxr-xr-x  43 root  wheel  1376 Mar 17 21:34 ..
drwxr-xr-x   9 root  wheel   288 Mar 17 21:34 Contents
jbo@McJbo Calculator.app % cd Contents
jbo@McJbo Contents % ll
total 16
drwxr-xr-x    9 root  wheel   288 Mar 17 21:34 .
drwxr-xr-x    3 root  wheel    96 Mar 17 21:34 ..
-rw-r--r--    1 root  wheel  2147 Mar 17 21:34 Info.plist
drwxr-xr-x    3 root  wheel    96 Mar 17 21:34 MacOS
-rw-r--r--  204 root  wheel     8 Mar 17 21:34 PkgInfo
drwxr-xr-x    4 root  wheel   128 Mar 17 21:34 PlugIns
drwxr-xr-x   54 root  wheel  1728 Mar 17 21:34 Resources
drwxr-xr-x    3 root  wheel    96 Mar 17 21:34 _CodeSignature
-rw-r--r--    1 root  wheel   461 Mar 17 21:34 version.plist
jbo@McJbo Contents % cd MacOS
jbo@McJbo MacOS % ll
total 344
drwxr-xr-x  3 root  wheel      96 Mar 17 21:34 .
drwxr-xr-x  9 root  wheel     288 Mar 17 21:34 ..
-rwxr-xr-x  1 root  wheel  540912 Mar 17 21:34 Calculator
jbo@McJbo MacOS %

보시다시피, Calculator.app은 디렉터리입니다. 그 아래에는 단일 항목 - Contents라는 또 다른 디렉터리 - 이 있습니다. Contents 아래에는 여러 항목이 있습니다:

  • Info.plist - 앱에 대한 메타데이터를 포함합니다. 이에 대해서는 나중에 더 자세히 다룹니다.
  • MacOS - 앱의 기본 실행 파일을 포함합니다(세 번째 디렉터리 목록에서 볼 수 있듯이).
  • PkgInfo - 선택 사항. 패키지 정보를 포함하는 이진 파일입니다.
  • PlugIns - 선택 사항. 앱의 플러그인을 포함할 수 있는 디렉터리입니다. Calculator에는 두 개가 있습니다. 하나는 "Basic and Scientific"용이고 다른 하나는 "Hexadecimal"용입니다(왜 그렇게 나누었는지 정말 모르겠고, 관심도 없습니다).
  • Resources - 선택 사항. 이름에서 알 수 있듯이 리소스를 포함합니다. 아이콘이 있는 .icns 파일과 지역화와 관련된 .lprroj 접미사가 있는 디렉터리 등 여러 항목을 찾을 수 있습니다.
  • _CodeSignature - 선택 사항. 이름에서 알 수 있듯이 코드 서명 정보를 포함합니다.
  • version.plist - 선택 사항, 버전 정보를 포함합니다.

공식적으로 필수인 항목은 거의 없다는 점에 유의하세요. 사실, 우리는 아무것도 컴파일하지 않고도 우리만의 첫 번째 앱을 만들 수 있습니다! 하지만 먼저 Info.plist 파일에 대해 논의해야 합니다.

Property list 파일

macOS를 더 많이 살펴볼수록 이런 이상한 파일들을 더 많이 발견하게 될 것입니다. 이것들은 그저 화려하게 포장된 구성 파일에 불과합니다. 항상 .plist 확장자를 가지며, 이는 공식 이름인 Property list 파일의 짧은 표현입니다. 안타깝게도 Apple이 유지 관리하는 3가지 서로 다른 plist 형식이 있습니다:

  • 사람이 읽을 수 있는 xml 형식.
  • 널리 사용되지 않는 json 형식.
  • 이진 형식으로, 보통 bplist 텍스트가 매직으로 표시됩니다.

다행히도 모든 형식을 지원하는 plutil이라는 유틸리티가 있습니다. plist 파일을 출력하려면 plutil -p를 사용하면 됩니다. 예를 들어:

root@kitploit:~
jbo@McJbo Contents % plutil -p Info.plist | head -n 20
{
  "BuildMachineOSBuild" => "22A380007"
  "CFBundleDevelopmentRegion" => "English"
  "CFBundleExecutable" => "Calculator"
  "CFBundleGetInfoString" => "10.14, Copyright © 2000-2018, Apple Inc."
  "CFBundleHelpBookFolder" => "Calculator.help"
  "CFBundleHelpBookName" => "com.apple.Calculator.help"
  "CFBundleIconFile" => "AppIcon"
  "CFBundleIconName" => "AppIcon"
  "CFBundleIdentifier" => "com.apple.calculator"
  "CFBundleInfoDictionaryVersion" => "6.0"
  "CFBundleName" => "Calculator"
  "CFBundlePackageType" => "APPL"
  "CFBundleShortVersionString" => "10.16"
  "CFBundleSignature" => "????"
  "CFBundleSupportedPlatforms" => [
    0 => "MacOSX"
  ]
  "CFBundleVersion" => "223"
  "CTIgnoreUserFonts" => 1
jbo@McJbo Contents %

plutil에는 변환 기능도 내장되어 있습니다. 지금은 그것들을 시연하지는 않겠습니다. Apple은 앱의 Info.plist에서 몇 가지 요구 사항을 문서화하고 있지만, 실제로 필수인 필드는 거의 없습니다. 몇 가지 흥미로운 필드는 다음과 같습니다:

  • CFBundleExecutable - 기본 실행 파일의 이름으로, MacOS 디렉터리 아래에 있을 것으로 예상됩니다.
  • CFBundleIconFile - 아이콘 파일의 이름. 선택 사항.
  • CFBundleIdentifier - 앱 번들의 식별자. Apple은 역DNS 표기법(예: com.apple.calculator)을 사용할 것을 권장합니다.
  • CFBundleName - 번들 이름.

이를 염두에 두고, 우리는 코딩조차 하지 않고 우리만의 첫 번째 멋진 앱을 만들 수 있습니다! 한번 보세요:

root@kitploit:~
#!/bin/zsh

# Create Bundle structure
mkdir -p ./MyApp.app/Contents/MacOS

# Create main executable file - a shell script in our case
cat <<EOF > ./MyApp.app/Contents/MacOS/MyApp
#!/bin/zsh
osascript -e 'tell app "Finder" to display dialog "Hello from MyApp!"'
EOF
chmod +x ./MyApp.app/Contents/MacOS/MyApp

# Create the Info.plist file
cat <<EOF > ./MyApp.app/Contents/Info.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>CFBundleExecutable</key>
	<string>MyApp</string>
	<key>CFBundleIdentifier</key>
	<string>com.myapp</string>
	<key>CFBundleName</key>
	<string>MyApp</string>
	<key>CFBundlePackageType</key>
	<string>APPL</string>
</dict>
</plist>
EOF

이렇게 하면 MyApp이라는 새 앱이 생성됩니다. 클릭하면 zsh 스크립트(MyApp이라고 함)가 실행될 뿐입니다. osascript를 사용한다는 점에 유의하세요. 이는 AppleScript 인터프리터이자 완전한 골칫거리이지만, 단지 Hello from MyApp!이라는 대화상자를 표시할 것입니다. 물론 그 zsh 셸 파일에 임의의 코드를 작성할 수 있습니다. 최신 macOS 버전에서는 zsh가 osascript를 호출하도록 허용할지 묻는 프롬프트가 표시될 수 있습니다. 왜 그런 일이 발생하는지는 향후 게시물에서 논의하겠지만, 첫 번째 승인 후에는 묻지 않는다는 점에 유의하세요.

앱 실행

앱을 실행한다는 것은 여전히 프로세스가 생성된다는 뜻입니다. 당연히 CFBundleExecutable이 가리키는 프로세스입니다. 그 프로세스는 무엇 아래에서 실행될까요? 확인해 봅시다:

root@kitploit:~
jbo@McJbo ~ % open -a Calculator
jbo@McJbo ~ % ps -A -j | grep Calculator | grep -v grep
jbo              12067     1 12067      0    1 S      ??    0:00.41 /System/Applications/Calculator.app/Contents/MacOS/Calculator
jbo@McJbo ~ %

open 명령은 Calculator 앱을 더블 클릭하는 것과 동일합니다. 꽤 흥미로우며 곧 논의하겠습니다. 이제 Calculator가 실행 중이므로 ps를 사용하여 실행 중인 프로세스를 표시합니다. 예상대로 /System/Applications/Calculator.app/Contents/MacOS/Calculator가 실행 중인 프로세스이며 PID는 12067입니다. 그러나 부모 프로세스 ID는 1입니다!

macOS에서 프로세스 ID 1은 /sbin/launchd입니다. 이는 "시스템 전체 및 사용자별 데몬/에이전트 관리자"입니다. Windows 배경에서 왔다면 services.exe로, Linux에 익숙하다면 systemd로 상상할 수 있습니다. 서비스(macOS에서는 Launch Agents 및 Launch Daemons라고 함)를 관리하는 것 외에도 모든 앱의 부모이기도 하며, 이는 macOS에서 의미 있는 프로세스 트리를 얻는 것이 어려운 이유 중 하나입니다.

흥미롭게도 /System/Applications/Calculator.app/Contents/MacOS/Calculator를 직접 호출하여 Calculator 앱을 단순한 프로세스로 실행할 수도 있지만, 그 경우에는 launchd의 자식이 아닙니다:

root@kitploit:~
jbo@McJbo ~ % /System/Applications/Calculator.app/Contents/MacOS/Calculator &
[1] 12502
jbo@McJbo ~ % 2023-04-04 15:54:22.987 Calculator[12502:1297087] XType: XTFontStaticRegistry is enabled by Info.plist.

jbo@McJbo ~ % ps -A -j | grep Calculator | grep -v grep
jbo              12502   951 12502      0    1 SN   s000    0:00.31 /System/Applications/Calculator.app/Contents/MacOS/Calculator
jbo@McJbo ~ % echo $$
951
jbo@McJbo ~ %

실제로 Calculator는 정상적으로 실행되지만, 이제는 우리 터미널의 자식 프로세스입니다. 우리가 본 동작에서 주목할 점은 공격자가 이를 다른 목적으로 사용할 수 있다는 것입니다. 예를 들어, 공격자는 보안 도구를 회피하기 위해 프로세스 트리에서 쉽게 벗어날 수 있으며, 로직 취약점을 악용할 수도 있습니다(시간이 있다면 제 macOS 샌드박스 탈출 취약점 분석 글을 읽어 보세요).

launchd에는 다른 흥미로운 역할도 있습니다(LaunchAgents 및 LaunchDaemons에 대해 읽어 보세요). 하지만 지금은 이에 대해 논의하지 않겠습니다.

번들에 대해 더 알아보기

여기서 한 가지 유형의 번들을 보여드렸지만 더 많은 유형이 있습니다(완전한 목록은 아닙니다):

  • .app - 이미 본 것으로, 앱의 컨테이너인 Application Bundles입니다.
  • .framework - 로드 가능한 번들인 Frameworks를 포함합니다. 네, macOS에서는 로드 가능한 파일(.dylib)에 dlopen을 호출하거나 전체 프레임워크 번들(리소스, 코드 등 포함)을 로드할 수 있습니다.
  • .kext - 커널 확장을 포함합니다. macOS 커널에 대한 로드 가능한 번들이지만, 최근 OS 버전에서 Apple은 커널 확장 수를 줄이기 위해 정말 많은 노력을 기울이고 있습니다.
  • .plugin - 이름에서 알 수 있듯이 플러그인을 위한 컨테이너입니다.

요약

이 글은 macOS 연구로 전환하는 사람들을 돕기 위한 일련의 짧은 블로그 게시물 중 첫 번째입니다.
공격 보안 관점에서 가장 먼저 눈에 띈 것은 페이로드를 멋진 앱 구조로 패키징하는 것이 얼마나 쉬운지였습니다.
하지만 상황은 그렇게 단순하지 않습니다. 다음 몇 개의 블로그 게시물에서는 macOS의 많은 보안 기능 때문에 코드 실행을 얻는 것이 그렇게 간단하지 않다는 것을 발견하게 될 것입니다.

계속 지켜봐 주세요!

Jonathan Bar Or (https://jonathanbaror.com)

도구 다운로드