hacktricks/macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing
2023-09-19 23:09:04 +00:00
..
arm64-basic-assembly.md Translated ['exploiting/linux-exploiting-basic-esp/README.md', 'macos-ha 2023-09-14 00:12:24 +00:00
introduction-to-x64.md Translated ['macos-hardening/macos-security-and-privilege-escalation/mac 2023-09-19 23:09:04 +00:00
README.md Translated ['exploiting/linux-exploiting-basic-esp/README.md', 'macos-ha 2023-09-14 00:12:24 +00:00

macOSアプリ - 検査、デバッグ、およびFuzzing

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥

静的解析

otool

otool -L /bin/ls #List dynamically linked libraries
otool -tv /bin/ps #Decompile application

objdump

{% code overflow="wrap" %}

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

{% endcode %}

jtool2

このツールは、codesignotool、およびobjdump代替として使用することができ、いくつかの追加機能も提供します。ここからダウンロードするか、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

Codesign

Codesignコードサインは、macOSにおけるアプリケーションの署名プロセスです。アプリケーションをコードサインすることで、そのアプリケーションが信頼できるものであることを証明し、ユーザーに安全性を提供します。

コードサインには、開発者証明書を使用します。開発者証明書は、Apple Developer Programに登録することで入手できます。アプリケーションをコードサインするには、開発者証明書を使用してアプリケーションにデジタル署名を付ける必要があります。

コードサインされたアプリケーションは、macOSにおいて信頼されたアプリケーションとして扱われます。ユーザーがコードサインされたアプリケーションを実行する際には、macOSがアプリケーションの署名を検証し、信頼性を確認します。

コードサインは、アプリケーションの改ざんや不正な変更を防ぐために重要です。また、コードサインによって、アプリケーションが正当な権限を持つことも確認されます。

コードサインのプロセスは、アプリケーションのセキュリティと特権エスカレーションの観点から重要です。正当なアプリケーションのコードサインを確認することで、悪意のあるアプリケーションや攻撃者による特権エスカレーションを防ぐことができます。

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

# Check if the apps 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

SuspiciousPackage

SuspiciousPackageは、インストールする前に**.pkg**ファイル(インストーラ)を調査し、中身を確認するのに役立つツールです。
これらのインストーラには、マルウェアの作者が通常悪用するpreinstallpostinstallのbashスクリプトが含まれています。

hdiutil

このツールは、Appleのディスクイメージ.dmg)ファイルを実行する前に調査するためにマウントすることができます。

hdiutil attach ~/Downloads/Firefox\ 58.0.2.dmg

Objective-C

メタデータ

{% hint style="danger" %} Objective-Cで書かれたプログラムは、Mach-Oバイナリにコンパイルされるときに、クラスの宣言を保持します。このクラスの宣言には、以下の情報が含まれます: {% endhint %}

  • クラス
  • クラスメソッド
  • クラスのインスタンス変数

これらの情報は、class-dumpを使用して取得できます。

class-dump Kindle.app

関数の呼び出し

Objective-Cを使用するバイナリで関数が呼び出されると、コンパイルされたコードはその関数を呼び出す代わりに**objc_msgSend**を呼び出します。これにより、最終的な関数が呼び出されます。

この関数が期待するパラメータは次のとおりです:

  • 最初のパラメータ(selfは、「メッセージを受け取るクラスのインスタンスを指すポインタ」です。簡単に言えば、メソッドが呼び出されるオブジェクトです。メソッドがクラスメソッドの場合、これはクラスオブジェクト全体としてのインスタンスになります。一方、インスタンスメソッドの場合、selfはクラスのインスタンスとしてインスタンス化されたオブジェクトを指します。
  • 2番目のパラメータop)は、「メッセージを処理するメソッドのセレクタ」です。簡単に言えば、これはメソッドの名前です。
  • 残りのパラメータは、メソッドで必要なですop
引数 レジスタ (for) objc_msgSend
1番目の引数 rdi self: メソッドが呼び出されるオブジェクト
2番目の引数 rsi op: メソッドの名前
3番目の引数 rdx メソッドへの最初の引数
4番目の引数 rcx メソッドへの2番目の引数
5番目の引数 r8 メソッドへの3番目の引数
6番目の引数 r9 メソッドへの4番目の引数
7番目以降の引数

rsp+
(スタック上)

メソッドへの5番目以降の引数

Swift

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
[...]

詳細な情報は、このブログ記事でこれらのセクションに保存されている情報についての詳細を見つけることができます。

パックされたバイナリ

  • 高いエントロピーをチェックする
  • 文字列をチェックする(ほとんど理解できない文字列がある場合は、パックされている)
  • MacOS用のUPXパッカーは、"__XHDR"というセクションを生成します

動的解析

{% hint style="warning" %} バイナリをデバッグするには、SIPを無効にする必要がありますcsrutil disableまたはcsrutil enable --without debug)またはバイナリを一時フォルダにコピーしてcodesign --remove-signature <binary-path>で署名を削除するか、バイナリのデバッグを許可します(このスクリプトを使用できます) {% endhint %}

{% hint style="warning" %} macOS上のシステムバイナリcloudconfigurationdなど)をインストゥルメントするには、SIPを無効にする必要があります(署名を削除するだけでは機能しません)。 {% endhint %}

統合ログ

MacOSは、アプリケーションを実行する際に非常に役立つ多くのログを生成します。これにより、アプリケーションが何をしているかを理解することができます。

さらに、一部のログには、一部のユーザーまたはコンピューター識別可能な情報を非表示にするためのタグ<private>が含まれています。ただし、この情報を開示するためには、証明書をインストールすることが可能です。こちらの説明に従ってください。

Hopper

左パネル

Hopperの左パネルでは、バイナリのシンボルラベル)、手続きと関数のリスト(Proc)、および文字列(Strを表示することができます。これらはすべての文字列ではありませんが、Mac-Oファイルのいくつかの部分_cstringやobjc_methnameなど)で定義されているものです。

中央パネル

中央パネルでは、逆アセンブルされたコードを表示することができます。また、生の逆アセンブル、グラフ逆コンパイルバイナリのいずれかをクリックして表示することができます。

コードオブジェクトを右クリックすると、そのオブジェクトへの参照や名前の変更(これは逆コンパイルされた擬似コードでは機能しません)を確認することができます。

さらに、中央下部にはPythonコマンドを記述することができます。

右パネル

右パネルでは、ナビゲーション履歴(現在の状況に到達するまでの経緯を知るため)、この関数を呼び出すすべての関数とこの関数が呼び出すすべての関数を表示する呼び出しグラフ、およびローカル変数の情報など、興味深い情報を表示することができます。

dtrace

これにより、ユーザーは非常に低レベルでアプリケーションにアクセスでき、ユーザーはプログラムをトレースしたり、実行フローを変更したりすることができます。Dtraceは、カーネル全体に配置されるプローブを使用します。これらのプローブは、システムコールの開始と終了時などの場所に配置されています。

DTraceは、各システムコールのエントリポイントと終了ポイントでプローブを作成するために**dtrace_probe_create**関数を使用します。これらのプローブは、各システムコールのエントリと終了時に発火することができます。DTraceとのやり取りは、ルートユーザーにのみ利用可能な/dev/dtraceを介して行われます。

{% hint style="success" %} SIP保護を完全に無効にせずにDtraceを有効にするには、回復モードで次のコマンドを実行できますcsrutil enable --without dtrace

また、自分でコンパイルしたバイナリを**dtraceまたはdtruss**で実行することもできます。 {% endhint %}

利用可能な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の4つの部分で構成されています。名前の一部を指定しない場合、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 is a command-line tool available on macOS that allows you to trace and inspect system calls made by a running application. It can be used for debugging and analyzing the behavior of macOS applications.

To use dtruss, you need to specify the target application's process ID (PID) or its name. Once dtruss is attached to the target application, it intercepts and displays the system calls made by the application in real-time.

The output of dtruss includes information such as the system call number, arguments, return values, and any errors encountered. This can be helpful in understanding how an application interacts with the underlying operating system and identifying potential security vulnerabilities or performance issues.

Here's an example of using dtruss to trace the system calls made by an application with a specific PID:

$ sudo dtruss -p <PID>

Alternatively, you can use the application's name instead of the PID:

$ sudo dtruss -n <application_name>

Keep in mind that dtruss requires root privileges to attach to a running application. Additionally, it may impact the performance of the traced application, so it's recommended to use it in a controlled environment or on a test system.

Note: dtruss has been deprecated in recent versions of macOS and replaced by dtrace. However, it can still be used on older macOS versions for inspecting and debugging applications.

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

ktrace

これは、SIPが有効化されている場合でも使用できます

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

ProcessMonitor

ProcessMonitorは、プロセスが実行しているプロセス関連のアクション(例:プロセスが作成している新しいプロセスを監視する)をチェックするための非常に便利なツールです。

FileMonitor

FileMonitorは、ファイルの作成、変更、削除などのファイルイベントを監視し、その詳細な情報を提供します。

Crescendo

Crescendoは、WindowsユーザーがMicrosoft Sysinternalの_Procmon_から知っている外観と操作感を持つ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

lldbは、macOSバイナリのデバッグにおけるデファクトツールです。

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

{% hint style="warning" %} lldb内で、process save-coreを使用してプロセスをダンプします。 {% endhint %}

(lldb) コマンド説明
run (r)ブレークポイントがヒットするか、プロセスが終了するまで、実行を開始します。
continue (c)デバッグ対象のプロセスの実行を継続します。
nexti (n / ni)次の命令を実行します。このコマンドは関数呼び出しをスキップします。
stepi (s / si)次の命令を実行します。nextiコマンドとは異なり、このコマンドは関数呼び出しに入ります。
finish (f)現在の関数("フレーム")の残りの命令を実行し、停止します。
control + c実行を一時停止します。プロセスが実行されている場合、これによりプロセスは現在の実行位置で停止します。
breakpoint (b)

b main # mainという名前の関数

b <binname>`main # バイナリのメイン関数

b set -n main --shlib <lib_name> # 指定されたバイナリのメイン関数

b -[NSDictionary objectForKey:]

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>メモリをヌル終端文字列として表示します。
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を使用してください

memorymemory 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 # 現在のアドレスから逆アセンブルを開始する

parrayparray 3 (char **)$x1 # x1レジスタの3つの要素の配列をチェックする

{% hint style="info" %} **objc_sendMsg**関数を呼び出す際、rsiレジスタにはメソッドの名前がヌル終端("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:" {% endhint %}

アンチダイナミック解析

VM検出

  • **sysctl hw.model**コマンドは、ホストがMacOSである場合には「Mac」を返しますが、VMの場合は異なる値を返します。
  • **hw.logicalcpuhw.physicalcpu**の値を操作することで、一部のマルウェアはVMかどうかを検出しようとします。
  • 一部のマルウェアは、MACアドレス00:50:56に基づいてマシンがVMwareであるかどうかを検出することもできます。
  • 単純なコードを使用して、プロセスがデバッグされているかどうかを検出することもできます:
  • if(P_TRACED == (info.kp_proc.p_flag & P_TRACED)){ //process being debugged }
  • **ptraceシステムコールをPT_DENY_ATTACH**フラグとともに呼び出すこともできます。これにより、デバッガがアタッチおよびトレースを行うことができなくなります。
  • sysctlまたはptrace関数がインポートされているかどうかを確認することができます(ただし、マルウェアは動的にインポートする可能性があります)。
  • この記事によると、"Defeating Anti-Debug Techniques: macOS ptrace variants"
    "メッセージ「Process # exited with status = 45 (0x0000002d)」は、デバッグ対象がPT_DENY_ATTACHを使用していることを示す兆候です。"

Fuzzing

ReportCrash

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

スリープ

MacOSでのフジング中には、Macがスリープしないようにすることが重要です。

  • systemsetup -setsleep Never
  • pmset、システム環境設定
  • KeepingYouAwake

SSHの切断

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

内部ハンドラ

次のページをチェックアウトして、指定されたスキームやプロトコルを処理するアプリを見つける方法を見つけてください:

{% content-ref url="../macos-file-extension-apps.md" %} macos-file-extension-apps.md {% endcontent-ref %}

ネットワークプロセスの列挙

ネットワークデータを管理しているプロセスを見つけるのに興味深いです:

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

{% code overflow="wrap" %}

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"

ファズツール

AFL++

CLIツールに対応しています。

Litefuzz

macOSのGUIツールとの互換性があります。ただし、一部のmacOSアプリは固有の要件を持っています。例えば、ユニークなファイル名、正しい拡張子、サンドボックスからのファイルの読み取り(~/Library/Containers/com.apple.Safari/Data)が必要です。

以下にいくつかの例を示します:

{% code overflow="wrap" %}

# 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

{% endcode %}

より多くのMacOS情報のFuzzing

参考文献

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥