hacktricks/macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing
2023-10-15 10:01:52 +00:00
..
arm64-basic-assembly.md Translated ['macos-hardening/macos-security-and-privilege-escalation/mac 2023-10-12 16:27:09 +00:00
introduction-to-x64.md Translated ['macos-hardening/macos-security-and-privilege-escalation/mac 2023-10-09 20:03:11 +00:00
README.md Translated ['macos-hardening/macos-security-and-privilege-escalation/mac 2023-10-15 10:01:52 +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

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

Codesign / ldid

{% hint style="danger" %} CodesignmacOSに見つけることができますが、ldidiOSに見つけることができます。 {% endhint %}

# 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

# 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

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

以下のブログ記事で、これらのセクションに格納されている情報に関する詳細情報を見つけることができます:このブログ記事

さらに、Swiftバイナリにはシンボルが含まれている場合があります(たとえば、ライブラリは関数を呼び出すためにシンボルを格納する必要があります)。シンボルには通常、関数名や属性に関する情報が含まれており、見た目は醜いですが非常に便利です。したがって、オリジナルの名前を取得できる「デマングラー」があります。

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

# Swift cli
swift demangle

パックされたバイナリ

  • 高いエントロピーをチェックする
  • 文字列をチェックする(ほとんど理解できない文字列がある場合は、パックされている可能性がある)
  • 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は、各システムコールのエントリポイントと終了ポイントでプローブを作成するために**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. The tool will then intercept and display the system calls made by the application, along with their arguments and return values.

Here's an example of how to use dtruss:

$ sudo dtruss -p <PID>

Replace <PID> with the process ID of the target application. Running dtruss with root privileges (sudo) is necessary to trace system calls made by other processes.

dtruss can be a powerful tool for understanding how an application interacts with the underlying macOS system. It can help identify potential security vulnerabilities or performance issues by inspecting the system calls made by the application.

Note: dtruss is a debugging tool and should only be used for legitimate purposes, such as debugging or analyzing software behavior.

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

SpriteTree

SpriteTreeは、プロセス間の関係を表示するツールです。
**sudo eslogger fork exec rename create > cap.json**のようなコマンドでMacを監視する必要がありますこのコマンドを実行するためにはFDAが必要です。そして、このツールでjsonを読み込んですべての関係を表示することができます

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

これにより、lldbはIntel構文を使用してx86アセンブリを表示します。

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実行を一時停止します。プロセスが実行rまたは継続cされている場合、プロセスは現在の実行位置で停止します。
breakpoint (b)

b main # main関数が呼び出される場所

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

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

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 # 1つのアドレスからもう一方まで逆アセンブルする
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.logicalcpuおよびhw.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を使用していることを示す兆候です"

ファジング

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 🎥