macOS Apps - Inspecting, debugging and Fuzzing

Support HackTricks

정적 분석

otool & objdump & nm

otool -L /bin/ls #List dynamically linked libraries
otool -tv /bin/ps #Decompile application
objdump -m --dylibs-used /bin/ls #List dynamically linked libraries
objdump -m -h /bin/ls # Get headers information
objdump -m --syms /bin/ls # Check if the symbol table exists to get function names
objdump -m --full-contents /bin/ls # Dump every section
objdump -d /bin/ls # Dissasemble the binary
objdump --disassemble-symbols=_hello --x86-asm-syntax=intel toolsdemo #Disassemble a function using intel flavour
nm -m ./tccd # List of symbols

jtool2 & Disarm

You can 여기에서 disarm을 다운로드하세요.

ARCH=arm64e disarm -c -i -I --signature /path/bin # Get bin info and signature
ARCH=arm64e disarm -c -l /path/bin # Get binary sections
ARCH=arm64e disarm -c -L /path/bin # Get binary commands (dependencies included)
ARCH=arm64e disarm -c -S /path/bin # Get symbols (func names, strings...)
ARCH=arm64e disarm -c -d /path/bin # Get disasembled
jtool2 -d __DATA.__const myipc_server | grep MIG # Get MIG info

여기에서 jtool2를 다운로드하세요 또는 brew로 설치할 수 있습니다.

# Install
brew install --cask jtool2

jtool2 -l /bin/ls # Get commands (headers)
jtool2 -L /bin/ls # Get libraries
jtool2 -S /bin/ls # Get symbol info
jtool2 -d /bin/ls # Dump binary
jtool2 -D /bin/ls # Decompile binary

# Get signature information
ARCH=x86_64 jtool2 --sig /System/Applications/Automator.app/Contents/MacOS/Automator

# Get MIG information
jtool2 -d __DATA.__const myipc_server | grep MIG

jtool은 disarm을 위해 더 이상 사용되지 않습니다

Codesign / ldid

**Codesign**은 macOS에서 찾을 수 있으며 **ldid**는 iOS에서 찾을 수 있습니다

# Get signer
codesign -vv -d /bin/ls 2>&1 | grep -E "Authority|TeamIdentifier"

# Check if the app’s contents have been modified
codesign --verify --verbose /Applications/Safari.app

# Get entitlements from the binary
codesign -d --entitlements :- /System/Applications/Automator.app # Check the TCC perms

# Check if the signature is valid
spctl --assess --verbose /Applications/Safari.app

# Sign a binary
codesign -s <cert-name-keychain> toolsdemo

# Get signature info
ldid -h <binary>

# Get entitlements
ldid -e <binary>

# Change entilements
## /tmp/entl.xml is a XML file with the new entitlements to add
ldid -S/tmp/entl.xml <binary>

SuspiciousPackage

SuspiciousPackage.pkg 파일(설치 프로그램)을 검사하고 설치하기 전에 내부 내용을 확인하는 데 유용한 도구입니다. 이 설치 프로그램에는 맬웨어 작성자가 일반적으로 맬웨어지속하기 위해 악용하는 preinstallpostinstall bash 스크립트가 포함되어 있습니다.

hdiutil

이 도구는 Apple 디스크 이미지(.dmg) 파일을 마운트하여 실행하기 전에 검사할 수 있도록 합니다:

hdiutil attach ~/Downloads/Firefox\ 58.0.2.dmg

It will be mounted in /Volumes

Packed binaries

  • 높은 엔트로피 확인

  • 문자열 확인 (이해할 수 있는 문자열이 거의 없으면, 패킹됨)

  • MacOS용 UPX 패커는 "__XHDR"라는 섹션을 생성합니다.

Static Objective-C analysis

Metadata

Objective-C로 작성된 프로그램은 Mach-O binaries로 컴파일될 때 클래스 선언을 유지합니다. 이러한 클래스 선언에는 다음의 이름과 유형이 포함됩니다:

  • 정의된 인터페이스

  • 인터페이스 메서드

  • 인터페이스 인스턴스 변수

  • 정의된 프로토콜

이 이름들은 이진 파일의 리버싱을 더 어렵게 만들기 위해 난독화될 수 있습니다.

Function calling

Objective-C를 사용하는 이진 파일에서 함수가 호출될 때, 컴파일된 코드는 해당 함수를 호출하는 대신 **objc_msgSend**를 호출합니다. 이는 최종 함수를 호출하게 됩니다:

이 함수가 기대하는 매개변수는 다음과 같습니다:

  • 첫 번째 매개변수 (self)는 "메시지를 받을 클래스의 인스턴스를 가리키는 포인터"입니다. 더 간단히 말하면, 메서드가 호출되는 객체입니다. 메서드가 클래스 메서드인 경우, 이는 클래스 객체의 인스턴스(전체)이며, 인스턴스 메서드의 경우, self는 클래스의 인스턴스화된 객체를 가리킵니다.

  • 두 번째 매개변수 (op)는 "메시지를 처리하는 메서드의 선택자"입니다. 다시 말해, 이는 단순히 메서드의 이름입니다.

  • 나머지 매개변수는 메서드(op)에 의해 필요한 값들입니다.

이 정보를 ARM64에서 lldb로 쉽게 얻는 방법은 이 페이지를 참조하세요:

Introduction to ARM64v8

x64:

Argument

Register

(for) objc_msgSend

1st argument

rdi

self: 메서드가 호출되는 객체

2nd argument

rsi

op: 메서드의 이름

3rd argument

rdx

메서드에 대한 1번째 인수

4th argument

rcx

메서드에 대한 2번째 인수

5th argument

r8

메서드에 대한 3번째 인수

6th argument

r9

메서드에 대한 4번째 인수

7th+ argument

rsp+ (스택에서)

메서드에 대한 5번째+ 인수

Dump ObjectiveC metadata

Dynadump

Dynadump는 Objective-C 이진 파일을 클래스 덤프하는 도구입니다. GitHub에서는 dylibs를 명시하지만, 실행 파일에도 작동합니다.

./dynadump dump /path/to/bin

At the time of the writing, this is 현재 가장 잘 작동하는 것.

일반 도구

nm --dyldinfo-only /path/to/bin
otool -ov /path/to/bin
objdump --macho --objc-meta-data /path/to/bin

class-dump

class-dump는 ObjetiveC 형식의 코드에서 클래스, 카테고리 및 프로토콜에 대한 선언을 생성하는 원래 도구입니다.

오래되었고 유지 관리되지 않아서 제대로 작동하지 않을 가능성이 높습니다.

ICDump

iCDump는 현대적이고 크로스 플랫폼 Objective-C 클래스 덤프입니다. 기존 도구와 비교할 때, iCDump는 Apple 생태계와 독립적으로 실행될 수 있으며 Python 바인딩을 노출합니다.

import icdump
metadata = icdump.objc.parse("/path/to/bin")

print(metadata.to_decl())

Static Swift analysis

Swift 바이너리의 경우, Objective-C 호환성 덕분에 때때로 class-dump를 사용하여 선언을 추출할 수 있지만 항상 가능한 것은 아닙니다.

jtool -l 또는 otool -l 명령어를 사용하면 __swift5 접두사로 시작하는 여러 섹션을 찾을 수 있습니다:

jtool2 -l /Applications/Stocks.app/Contents/MacOS/Stocks
LC 00: LC_SEGMENT_64              Mem: 0x000000000-0x100000000    __PAGEZERO
LC 01: LC_SEGMENT_64              Mem: 0x100000000-0x100028000    __TEXT
[...]
Mem: 0x100026630-0x100026d54        __TEXT.__swift5_typeref
Mem: 0x100026d60-0x100027061        __TEXT.__swift5_reflstr
Mem: 0x100027064-0x1000274cc        __TEXT.__swift5_fieldmd
Mem: 0x1000274cc-0x100027608        __TEXT.__swift5_capture
[...]

이 섹션에 저장된 정보에 대한 추가 정보는 이 블로그 게시물에서 확인할 수 있습니다.

게다가, Swift 바이너리는 기호를 가질 수 있습니다 (예: 라이브러리는 함수가 호출될 수 있도록 기호를 저장해야 합니다). **기호는 일반적으로 함수 이름과 속성에 대한 정보를 보기 좋지 않게 가지고 있으므로 매우 유용하며, 원래 이름을 얻을 수 있는 "디망글러"가 있습니다:

# Ghidra plugin
https://github.com/ghidraninja/ghidra_scripts/blob/master/swift_demangler.py

# Swift cli
swift demangle

동적 분석

이진 파일을 디버깅하려면 SIP를 비활성화해야 합니다 (csrutil disable 또는 csrutil enable --without debug) 또는 이진 파일을 임시 폴더로 복사하고 서명을 제거해야 합니다 codesign --remove-signature <binary-path> 또는 이진 파일의 디버깅을 허용해야 합니다 ( 이 스크립트를 사용할 수 있습니다).

macOS에서 시스템 이진 파일(예: cloudconfigurationd)을 계측하려면 SIP를 비활성화해야 합니다 (서명만 제거하는 것으로는 작동하지 않습니다).

API

macOS는 프로세스에 대한 정보를 제공하는 몇 가지 흥미로운 API를 노출합니다:

  • proc_info: 각 프로세스에 대한 많은 정보를 제공하는 주요 API입니다. 다른 프로세스 정보를 얻으려면 root 권한이 필요하지만 특별한 권한이나 mach 포트는 필요하지 않습니다.

  • libsysmon.dylib: XPC로 노출된 함수를 통해 프로세스에 대한 정보를 얻을 수 있게 해주지만, com.apple.sysmond.client 권한이 필요합니다.

스택샷 및 마이크로스택샷

스택샷팅은 프로세스의 상태를 캡처하는 기술로, 모든 실행 중인 스레드의 호출 스택을 포함합니다. 이는 디버깅, 성능 분석 및 특정 시점에서 시스템의 동작을 이해하는 데 특히 유용합니다. iOS 및 macOS에서는 sample 및 **spindump**와 같은 여러 도구와 방법을 사용하여 스택샷팅을 수행할 수 있습니다.

Sysdiagnose

이 도구 (/usr/bini/ysdiagnose)는 기본적으로 ps, zprint와 같은 수십 개의 다양한 명령을 실행하여 컴퓨터에서 많은 정보를 수집합니다.

root로 실행해야 하며, 데몬 /usr/libexec/sysdiagnosedcom.apple.system-task-portsget-task-allow와 같은 매우 흥미로운 권한을 가지고 있습니다.

그의 plist는 /System/Library/LaunchDaemons/com.apple.sysdiagnose.plist에 위치하며, 3개의 MachServices를 선언합니다:

  • com.apple.sysdiagnose.CacheDelete: /var/rmp의 오래된 아카이브를 삭제합니다.

  • com.apple.sysdiagnose.kernel.ipc: 특별 포트 23 (커널)

  • com.apple.sysdiagnose.service.xpc: Libsysdiagnose Obj-C 클래스를 통한 사용자 모드 인터페이스. 사전 정의된 세 가지 인수(compress, display, run)를 전달할 수 있습니다.

통합 로그

MacOS는 애플리케이션을 실행할 때 무엇을 하고 있는지 이해하는 데 매우 유용할 수 있는 많은 로그를 생성합니다.

게다가, <private> 태그가 포함된 로그가 있어 사용자 또는 컴퓨터 식별 가능한 정보를 숨깁니다. 그러나 이 정보를 공개하기 위해 인증서를 설치할 수 있습니다. 여기에서 설명을 따르세요.

호퍼

왼쪽 패널

호퍼의 왼쪽 패널에서는 이진 파일의 기호(Labels), 절차 및 함수 목록(Proc), 문자열(Str)을 볼 수 있습니다. 이들은 모든 문자열이 아니라 Mac-O 파일의 여러 부분(예: cstring 또는 objc_methname)에 정의된 문자열입니다.

중간 패널

중간 패널에서는 디스어셈블된 코드를 볼 수 있습니다. 원시 디스어셈블, 그래프, 디컴파일된 코드 및 이진 파일로 각각의 아이콘을 클릭하여 볼 수 있습니다:

코드 객체를 오른쪽 클릭하면 해당 객체에 대한 참조를 보거나 이름을 변경할 수 있습니다 (이것은 디컴파일된 의사 코드에서는 작동하지 않습니다):

또한, 중간 하단에서 파이썬 명령을 작성할 수 있습니다.

오른쪽 패널

오른쪽 패널에서는 탐색 기록(현재 상황에 도달한 방법을 알 수 있음), 호출 그래프(이 함수를 호출하는 모든 함수와 이 함수가 호출하는 모든 함수), 지역 변수 정보를 포함한 흥미로운 정보를 볼 수 있습니다.

dtrace

dtrace는 사용자가 애플리케이션에 매우 저수준으로 접근할 수 있게 해주며, 사용자가 프로그램을 추적하고 실행 흐름을 변경할 수 있는 방법을 제공합니다. Dtrace는 프로브를 사용하며, 이는 커널 전역에 배치되어 시스템 호출의 시작과 끝과 같은 위치에 있습니다.

DTrace는 각 시스템 호출에 대한 프로브를 생성하기 위해 dtrace_probe_create 함수를 사용합니다. 이러한 프로브는 각 시스템 호출의 진입 및 종료 지점에서 발사될 수 있습니다. DTrace와의 상호작용은 /dev/dtrace를 통해 이루어지며, 이는 root 사용자만 사용할 수 있습니다.

SIP 보호를 완전히 비활성화하지 않고 Dtrace를 활성화하려면 복구 모드에서 다음을 실행할 수 있습니다: csrutil enable --without dtrace

또한 dtrace 또는 dtruss 이진 파일을 컴파일한 경우 사용할 수 있습니다.

dtrace의 사용 가능한 프로브는 다음과 같이 얻을 수 있습니다:

dtrace -l | head
ID   PROVIDER            MODULE                          FUNCTION NAME
1     dtrace                                                     BEGIN
2     dtrace                                                     END
3     dtrace                                                     ERROR
43    profile                                                     profile-97
44    profile                                                     profile-199

프로브 이름은 네 부분으로 구성됩니다: 제공자, 모듈, 함수 및 이름 (fbt:mach_kernel:ptrace:entry). 이름의 일부를 지정하지 않으면, Dtrace는 해당 부분을 와일드카드로 적용합니다.

DTrace를 구성하여 프로브를 활성화하고 프로브가 작동할 때 수행할 작업을 지정하려면 D 언어를 사용해야 합니다.

자세한 설명과 더 많은 예제는 https://illumos.org/books/dtrace/chp-intro.html에서 확인할 수 있습니다.

예제

man -k dtrace를 실행하여 사용 가능한 DTrace 스크립트를 나열합니다. 예: sudo dtruss -n binary

#Count the number of syscalls of each running process
sudo dtrace -n 'syscall:::entry {@[execname] = count()}'
  • 스크립트

syscall:::entry
/pid == $1/
{
}

#Log every syscall of a PID
sudo dtrace -s script.d 1234
syscall::open:entry
{
printf("%s(%s)", probefunc, copyinstr(arg0));
}
syscall::close:entry
{
printf("%s(%d)\n", probefunc, arg0);
}

#Log files opened and closed by a process
sudo dtrace -s b.d -c "cat /etc/hosts"
syscall:::entry
{
;
}
syscall:::return
{
printf("=%d\n", arg1);
}

#Log sys calls with values
sudo dtrace -s syscalls_info.d -c "cat /etc/hosts"

dtruss

dtruss -c ls #Get syscalls of ls
dtruss -c -p 1000 #get syscalls of PID 1000

kdebug

커널 추적 기능입니다. 문서화된 코드는 **/usr/share/misc/trace.codes**에서 찾을 수 있습니다.

latency, sc_usage, fs_usagetrace와 같은 도구는 내부적으로 이를 사용합니다.

kdebug와 인터페이스하기 위해 sysctlkern.kdebug 네임스페이스를 통해 사용되며, 사용할 MIB는 bsd/kern/kdebug.c에 구현된 함수가 있는 sys/sysctl.h에서 찾을 수 있습니다.

커스텀 클라이언트로 kdebug와 상호작용하기 위한 일반적인 단계는 다음과 같습니다:

  • KERN_KDSETREMOVE로 기존 설정 제거

  • KERN_KDSETBUF 및 KERN_KDSETUP으로 추적 설정

  • KERN_KDGETBUF로 버퍼 항목 수 가져오기

  • KERN_KDPINDEX로 추적에서 자신의 클라이언트 가져오기

  • KERN_KDENABLE로 추적 활성화

  • KERN_KDREADTR 호출로 버퍼 읽기

  • 각 스레드를 프로세스와 매칭하기 위해 KERN_KDTHRMAP 호출.

이 정보를 얻기 위해 Apple 도구 trace 또는 커스텀 도구 kDebugView (kdv)를 사용할 수 있습니다.

Kdebug는 한 번에 1명의 고객만 사용할 수 있습니다. 따라서 동시에 실행할 수 있는 k-debug 기반 도구는 하나뿐입니다.

ktrace

ktrace_* API는 libktrace.dylib에서 제공되며, 이는 Kdebug의 래퍼입니다. 그런 다음 클라이언트는 ktrace_session_createktrace_events_[single/class]를 호출하여 특정 코드에 대한 콜백을 설정하고 ktrace_start로 시작할 수 있습니다.

SIP가 활성화된 상태에서도 이 도구를 사용할 수 있습니다.

클라이언트로는 유틸리티 ktrace를 사용할 수 있습니다:

ktrace trace -s -S -t c -c ls | grep "ls("

Or tailspin.

kperf

이것은 커널 수준 프로파일링을 수행하는 데 사용되며 Kdebug 호출을 사용하여 구축됩니다.

기본적으로, 전역 변수 kernel_debug_active가 확인되고 설정되면 Kdebug 코드와 호출하는 커널 프레임의 주소로 kperf_kdebug_handler를 호출합니다. Kdebug 코드가 선택된 것과 일치하면 비트맵으로 구성된 "작업"을 가져옵니다(옵션은 osfmk/kperf/action.h를 확인하십시오).

Kperf에는 sysctl MIB 테이블도 있습니다: (루트로) sysctl kperf. 이 코드는 osfmk/kperf/kperfbsd.c에서 찾을 수 있습니다.

게다가, Kperf의 기능의 일부는 kpc에 존재하며, 이는 머신 성능 카운터에 대한 정보를 제공합니다.

ProcessMonitor

ProcessMonitor는 프로세스가 수행하는 프로세스 관련 작업을 확인하는 데 매우 유용한 도구입니다(예: 프로세스가 생성하는 새로운 프로세스를 모니터링).

SpriteTree

SpriteTree는 프로세스 간의 관계를 출력하는 도구입니다. **sudo eslogger fork exec rename create > cap.json**와 같은 명령으로 Mac을 모니터링해야 합니다(이를 실행하는 터미널은 FDA가 필요합니다). 그런 다음 이 도구에서 json을 로드하여 모든 관계를 볼 수 있습니다:

FileMonitor

FileMonitor는 파일 이벤트(생성, 수정 및 삭제와 같은)를 모니터링하여 이러한 이벤트에 대한 자세한 정보를 제공합니다.

Crescendo

Crescendo는 Microsoft Sysinternal의 _Procmon_에서 Windows 사용자가 알 수 있는 모양과 느낌을 가진 GUI 도구입니다. 이 도구는 다양한 이벤트 유형의 기록을 시작하고 중지할 수 있으며, 파일, 프로세스, 네트워크 등과 같은 카테고리별로 이러한 이벤트를 필터링할 수 있는 기능을 제공하고, 기록된 이벤트를 json 형식으로 저장할 수 있는 기능을 제공합니다.

Apple Instruments

Apple Instruments는 Xcode의 개발자 도구의 일부로, 애플리케이션 성능 모니터링, 메모리 누수 식별 및 파일 시스템 활동 추적에 사용됩니다.

fs_usage

프로세스가 수행하는 작업을 추적할 수 있습니다:

fs_usage -w -f filesys ls #This tracks filesystem actions of proccess names containing ls
fs_usage -w -f network curl #This tracks network actions

TaskExplorer

Taskexplorer는 이진 파일에서 사용되는 라이브러리, 사용 중인 파일네트워크 연결을 확인하는 데 유용합니다. 또한 이진 프로세스를 virustotal과 대조하여 이진 파일에 대한 정보를 보여줍니다.

PT_DENY_ATTACH

이 블로그 게시물에서는 **SIP가 비활성화되더라도 디버깅을 방지하기 위해 PT_DENY_ATTACH**를 사용한 실행 중인 데몬을 디버깅하는 방법에 대한 예제를 찾을 수 있습니다.

lldb

lldbmacOS 이진 디버깅을 위한 사실상의 도구입니다.

lldb ./malware.bin
lldb -p 1122
lldb -n malware.bin
lldb -n malware.bin --waitfor

당신은 홈 폴더에 다음 줄을 포함한 **.lldbinit**라는 파일을 생성하여 lldb를 사용할 때 intel 맛을 설정할 수 있습니다:

settings set target.x86-disassembly-flavor intel

lldb 내부에서 process save-core로 프로세스를 덤프합니다.

(lldb) 명령어

설명

run (r)

중단점에 도달하거나 프로세스가 종료될 때까지 계속 실행을 시작합니다.

process launch --stop-at-entry

진입점에서 중단하며 실행을 시작합니다.

continue (c)

디버깅 중인 프로세스의 실행을 계속합니다.

nexti (n / ni)

다음 명령어를 실행합니다. 이 명령어는 함수 호출을 건너뜁니다.

stepi (s / si)

다음 명령어를 실행합니다. nexti 명령어와 달리 이 명령어는 함수 호출로 들어갑니다.

finish (f)

현재 함수(“프레임”)의 나머지 명령어를 실행하고 반환 후 중단합니다.

control + c

실행을 일시 중지합니다. 프로세스가 실행(run)되었거나 계속(continue)되었다면, 현재 실행 중인 위치에서 프로세스가 중단됩니다.

breakpoint (b)

b main # main이라는 이름의 함수

b <binname>`main # 바이너리의 main 함수

b set -n main --shlib <lib_name> # 지정된 바이너리의 main 함수

breakpoint set -r '\[NSFileManager .*\]$' # 모든 NSFileManager 메서드

breakpoint set -r '\[NSFileManager contentsOfDirectoryAtPath:.*\]$'

break set -r . -s libobjc.A.dylib # 해당 라이브러리의 모든 함수에서 중단

b -a 0x0000000100004bd9

br l # 중단점 목록

br e/dis <num> # 중단점 활성화/비활성화

breakpoint delete <num>

help

help breakpoint # 중단점 명령어 도움말

help memory write # 메모리에 쓰기 위한 도움말

reg

reg read

reg read $rax

reg read $rax --format <format>

reg write $rip 0x100035cc0

x/s <reg/memory address>

메모리를 null로 종료된 문자열로 표시합니다.

x/i <reg/memory address>

메모리를 어셈블리 명령어로 표시합니다.

x/b <reg/memory address>

메모리를 바이트로 표시합니다.

print object (po)

이 명령어는 매개변수로 참조된 객체를 출력합니다.

po $raw

{

dnsChanger = {

"affiliate" = "";

"blacklist_dns" = ();

대부분의 Apple의 Objective-C API 또는 메서드는 객체를 반환하므로 “print object” (po) 명령어를 통해 표시해야 합니다. po가 의미 있는 출력을 생성하지 않으면 x/b를 사용하세요.

memory

memory read 0x000.... memory read $x0+0xf2a memory write 0x100600000 -s 4 0x41414141 # 해당 주소에 AAAA 쓰기 memory write -f s $rip+0x11f+7 "AAAA" # 해당 주소에 AAAA 쓰기

disassembly

dis # 현재 함수의 디스어셈블리

dis -n <funcname> # 함수의 디스어셈블리

dis -n <funcname> -b <basename> # 함수의 디스어셈블리 dis -c 6 # 6줄 디스어셈블리 dis -c 0x100003764 -e 0x100003768 # 한 주소에서 다른 주소까지 dis -p -c 4 # 현재 주소에서 디스어셈블리 시작

parray

parray 3 (char **)$x1 # x1 레지스터의 3개 구성 요소 배열 확인

image dump sections

현재 프로세스 메모리의 맵을 출력합니다.

image dump symtab <library>

image dump symtab CoreNLP # CoreNLP의 모든 기호 주소 가져오기

objc_sendMsg 함수를 호출할 때, rsi 레지스터는 null로 종료된 (“C”) 문자열로서 메서드의 이름을 보유합니다. lldb를 통해 이름을 출력하려면 다음과 같이 하세요:

(lldb) x/s $rsi: 0x1000f1576: "startMiningWithPort:password:coreCount:slowMemory:currency:"

(lldb) print (char*)$rsi: (char *) $1 = 0x00000001000f1576 "startMiningWithPort:password:coreCount:slowMemory:currency:"

(lldb) reg read $rsi: rsi = 0x00000001000f1576 "startMiningWithPort:password:coreCount:slowMemory:currency:"

동적 분석 방지

VM 탐지

  • sysctl hw.model 명령어는 호스트가 MacOS일 때 "Mac"을 반환하지만 VM일 때는 다른 값을 반환합니다.

  • hw.logicalcpu 및 **hw.physicalcpu**의 값을 조작하여 일부 악성코드는 VM인지 감지하려고 합니다.

  • 일부 악성코드는 MAC 주소(00:50:56)를 기반으로 VMware인지도 탐지할 수 있습니다.

  • 간단한 코드로 프로세스가 디버깅되고 있는지 확인할 수 있습니다:

  • if(P_TRACED == (info.kp_proc.p_flag & P_TRACED)){ //디버깅 중인 프로세스 }

  • ptrace 시스템 호출을 PT_DENY_ATTACH 플래그와 함께 호출할 수도 있습니다. 이는 디버거가 연결하고 추적하는 것을 방지합니다.

  • sysctl 또는 ptrace 함수가 가져와지는지 확인할 수 있습니다 (하지만 악성코드는 동적으로 가져올 수 있습니다).

  • 이 글에서 언급된 바와 같이, “디버그 방지 기술 무력화: macOS ptrace 변형” : “메시지 Process # exited with **status = 45 (0x0000002d)**는 디버그 대상이 PT_DENY_ATTACH를 사용하고 있다는 신호입니다.

코어 덤프

코어 덤프는 다음과 같은 경우에 생성됩니다:

  • kern.coredump sysctl이 1로 설정되어 있을 때 (기본값)

  • 프로세스가 suid/sgid가 아니거나 kern.sugid_coredump가 1일 때 (기본값은 0)

  • AS_CORE 제한이 작업을 허용할 때. ulimit -c 0을 호출하여 코드 덤프 생성을 억제할 수 있으며, ulimit -c unlimited로 다시 활성화할 수 있습니다.

이 경우 코어 덤프는 kern.corefile sysctl에 따라 생성되며 일반적으로 /cores/core/.%P에 저장됩니다.

퍼징

ReportCrash는 충돌하는 프로세스를 분석하고 충돌 보고서를 디스크에 저장합니다. 충돌 보고서는 개발자가 충돌 원인을 진단하는 데 도움이 되는 정보를 포함합니다. 사용자별 launchd 컨텍스트에서 실행되는 애플리케이션 및 기타 프로세스에 대해 ReportCrash는 LaunchAgent로 실행되며 사용자의 ~/Library/Logs/DiagnosticReports/에 충돌 보고서를 저장합니다. 데몬, 시스템 launchd 컨텍스트에서 실행되는 기타 프로세스 및 기타 권한 있는 프로세스에 대해 ReportCrash는 LaunchDaemon으로 실행되며 시스템의 /Library/Logs/DiagnosticReports에 충돌 보고서를 저장합니다.

충돌 보고서가 Apple로 전송되는 것이 걱정된다면 이를 비활성화할 수 있습니다. 그렇지 않으면 충돌 보고서는 서버가 어떻게 충돌했는지 파악하는 데 유용할 수 있습니다.

#To disable crash reporting:
launchctl unload -w /System/Library/LaunchAgents/com.apple.ReportCrash.plist
sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.ReportCrash.Root.plist

#To re-enable crash reporting:
launchctl load -w /System/Library/LaunchAgents/com.apple.ReportCrash.plist
sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.ReportCrash.Root.plist

Sleep

MacOS에서 퍼징할 때 Mac이 잠들지 않도록 하는 것이 중요합니다:

SSH Disconnect

SSH 연결을 통해 퍼징하는 경우 세션이 종료되지 않도록 하는 것이 중요합니다. 따라서 sshd_config 파일을 다음과 같이 변경하십시오:

  • TCPKeepAlive Yes

  • ClientAliveInterval 0

  • ClientAliveCountMax 0

sudo launchctl unload /System/Library/LaunchDaemons/ssh.plist
sudo launchctl load -w /System/Library/LaunchDaemons/ssh.plist

Internal Handlers

다음 페이지를 확인하세요 어떤 앱이 지정된 스킴 또는 프로토콜을 처리하는지 찾는 방법을 알아보세요:

macOS File Extension & URL scheme app handlers

Enumerating Network Processes

네트워크 데이터를 관리하는 프로세스를 찾는 것은 흥미롭습니다:

dtrace -n 'syscall::recv*:entry { printf("-> %s (pid=%d)", execname, pid); }' >> recv.log
#wait some time
sort -u recv.log > procs.txt
cat procs.txt

또는 netstat 또는 lsof를 사용하세요.

Libgmalloc

lldb -o "target create `which some-binary`" -o "settings set target.env-vars DYLD_INSERT_LIBRARIES=/usr/lib/libgmalloc.dylib" -o "run arg1 arg2" -o "bt" -o "reg read" -o "dis -s \$pc-32 -c 24 -m -F intel" -o "quit"

퍼저

CLI 도구에 작동합니다.

macOS GUI 도구와 "그냥 작동합니다". 일부 macOS 앱은 고유한 파일 이름, 올바른 확장자와 같은 특정 요구 사항이 있으며, 샌드박스에서 파일을 읽어야 합니다 (~/Library/Containers/com.apple.Safari/Data)...

몇 가지 예:

# iBooks
litefuzz -l -c "/System/Applications/Books.app/Contents/MacOS/Books FUZZ" -i files/epub -o crashes/ibooks -t /Users/test/Library/Containers/com.apple.iBooksX/Data/tmp -x 10 -n 100000 -ez

# -l : Local
# -c : cmdline with FUZZ word (if not stdin is used)
# -i : input directory or file
# -o : Dir to output crashes
# -t : Dir to output runtime fuzzing artifacts
# -x : Tmeout for the run (default is 1)
# -n : Num of fuzzing iterations (default is 1)
# -e : enable second round fuzzing where any crashes found are reused as inputs
# -z : enable malloc debug helpers

# Font Book
litefuzz -l -c "/System/Applications/Font Book.app/Contents/MacOS/Font Book FUZZ" -i input/fonts -o crashes/font-book -x 2 -n 500000 -ez

# smbutil (using pcap capture)
litefuzz -lk -c "smbutil view smb://localhost:4455" -a tcp://localhost:4455 -i input/mac-smb-resp -p -n 100000 -z

# screensharingd (using pcap capture)
litefuzz -s -a tcp://localhost:5900 -i input/screenshared-session --reportcrash screensharingd -p -n 100000

더 많은 퍼징 MacOS 정보

참고문헌

HackTricks 지원하기

Last updated