HackTricks
Search…
Pentesting
Powered By GitBook
MacOS Apps - Inspecting, debugging and Fuzzing

Static Analysis

otool

1
otool -L /bin/ls #List dynamically linked libraries
2
otool -tv /bin/ps #Decompile application
Copied!

SuspiciousPackage

SuspiciousPackage is a tool useful to inspect .pkg files (installers) and see what is inside before installing it. These installers have preinstall and postinstall bash scripts that malware authors usually abuse to persist the malware.

hdiutil

This tool allows to mount Apple disk images (.dmg) files to inspect them before running anything:
1
hdiutil attach ~/Downloads/Firefox\ 58.0.2.dmg
Copied!
It will be mounted in /Volumes

Objective-C

When a function is called in a binary that uses objective-C, the compiled code instead of calling that function, it will call objc_msgSend. Which will be calling the final function:
The params this function expects are:
    The first parameter (self) is "a pointer that points to the instance of the class that is to receive the message". Or more simply put, it’s the object that the method is being invoked upon. If the method is a class method, this will be an instance of the class object (as a whole), whereas for an instance method, self will point to an instantiated instance of the class as an object.
    The second parameter, (op), is "the selector of the method that handles the message". Again, more simply put, this is just the name of the method.
    The remaining parameters are any values that are required by the method (op).
Argument
Register
(for) objc_msgSend
1st argument
rdi
self: object that the method is being invoked upon
2nd argument
rsi
op: name of the method
3rd argument
rdx
1st argument to the method
4th argument
rcx
2nd argument to the method
5th argument
r8
3rd argument to the method
6th argument
r9
4th argument to the method
7th+ argument
rsp+ (on the stack)
5th+ argument to the method

Packed binaries

    Check for high entropy
    Check the strings (is there is almost no understandable string, packed)
    The UPX packer for MacOS generates a section called "__XHDR"

Dynamic Analysis

Note that in order to debug binaries, SIP needs to be disabled (csrutil disable or csrutil enable --without debug) or to copy the binaries to a temporary folder and remove the signature with codesign --remove-signature <binary-path> or allow the debugging of the binary (you can use this script)
Note that in order to instrument system binaries, (such as cloudconfigurationd) on macOS, SIP must be disabled (just removing the signature won't work).

dtruss

1
dtruss -c ls #Get syscalls of ls
2
dtruss -c -p 1000 #get syscalls of PID 1000
Copied!

ktrace

You can use this one even with SIP activated
1
ktrace trace -s -S -t c -c ls | grep "ls("
Copied!

dtrace

It allows users access to applications at an extremely low level and provides a way for users to trace programs and even change their execution flow. Dtrace uses probes which are placed throughout the kernel and are at locations such as the beginning and end of system calls.
The available probes of dtrace can be obtained with:
1
dtrace -l | head
2
ID PROVIDER MODULE FUNCTION NAME
3
1 dtrace BEGIN
4
2 dtrace END
5
3 dtrace ERROR
6
43 profile profile-97
7
44 profile profile-199
Copied!
The probe name consists of four parts: the provider, module, function, and name (fbt:mach_kernel:ptrace:entry). If you not specifies some part of the name, Dtrace will apply that part as a wildcard.
A more detailed explanation and more examples can be found in https://illumos.org/books/dtrace/chp-intro.html

Examples

    In line
1
#Count the number of syscalls of each running process
2
sudo dtrace -n 'syscall:::entry {@[execname] = count()}'
Copied!
    script
1
syscall:::entry
2
/pid == $1/
3
{
4
}
5
6
#Log every syscall of a PID
7
sudo dtrace -s script.d 1234
Copied!
1
syscall::open:entry
2
{
3
printf("%s(%s)", probefunc, copyinstr(arg0));
4
}
5
syscall::close:entry
6
{
7
printf("%s(%d)\n", probefunc, arg0);
8
}
9
10
#Log files opened and closed by a process
11
sudo dtrace -s b.d -c "cat /etc/hosts"
Copied!
1
syscall:::entry
2
{
3
;
4
}
5
syscall:::return
6
{
7
printf("=%d\n", arg1);
8
}
9
10
#Log sys calls with values
11
sudo dtrace -s syscalls_info.d -c "cat /etc/hosts"
Copied!

ProcessMonitor

ProcessMonitor is a very useful tool to check the process related actions a process is performing (for example, monitor which new processes a process is creating).

FileMonitor

FileMonitor allows to monitor file events (such as creation, modifications, and deletions) providing detailed information about such events.

fs_usage

Allows to follow actions performed by processes:
1
fs_usage -w -f filesys ls #This tracks filesystem actions of proccess names containing ls
2
fs_usage -w -f network curl #This tracks network actions
Copied!

TaskExplorer

Taskexplorer is useful to see the libraries used by a binary, the files it's using and the network connections. It also checks the binary processes against virustotal and show information about the binary.

lldb

lldb is the de facto tool for macOS binary debugging.
1
lldb ./malware.bin
2
lldb -p 1122
3
lldb -n malware.bin
4
lldb -n malware.bin --waitfor
Copied!
(lldb) Command
Description
run (r)
Starting execution, which will continue unabated until a breakpoint is hit or the process terminates.
continue (c)
Continue execution of the debugged process.
nexti (n)
Execute the next instruction. This command will skip over function calls.
stepi (s)
Execute the next instruction. Unlike the nexti command, this command will step into function calls.
finish (f)
Execute the rest of the instructions in the current function (“frame”) return and halt.
control + c
Pause execution. If the process has been run (r) or continued (c), this will cause the process to halt ...wherever it is currently executing.
breakpoint (b)
b main
b -[NSDictionary objectForKey:]
b 0x0000000100004bd9
br l #Breakpoint list
br e/dis <num> #Enable/Disable breakpoint
breakpoint delete <num>
help
help breakpoint #Get help of breakpoint command
help memory write #Get help to write into the memory
reg
reg read $rax
reg write $rip 0x100035cc0
x/s <reg/memory address>
Display the memory as a null-terminated string.
x/i <reg/memory address>
Display the memory as assembly instruction.
x/b <reg/memory address>
Display the memory as byte.
print object (po)
This will print the object referenced by the param
po $raw
{
dnsChanger = {
"affiliate" = "";
"blacklist_dns" = ();
Note that most of Apple’s Objective-C APIs or methods return objects, and thus should be displayed via the “print object” (po) command. If po doesn't produce a meaningful output use x/b
memory write
memory write 0x100600000 -s 4 0x41414141 #Write AAAA in that address
When calling the objc_sendMsg function, the rsi register holds the name of the method as a null-terminated (“C”) string. To print the name via lldb do:
(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:"

Anti-Dynamic Analysis

VM detection

    The command sysctl hw.model returns "Mac" when the host is a MacOS but something different when it's a VM.
    Playing with the values of hw.logicalcpu and hw.physicalcpu some malwares try to detect if it's a VM.
    Some malwares can also detect if the machine is VMware based on the MAC address (00:50:56).
    It's also possible to find if a process is being debugged with a simple code such us:
      if(P_TRACED == (info.kp_proc.p_flag & P_TRACED)){ //process being debugged }
    It can also invoke the ptrace system call with the PT_DENY_ATTACH flag. This prevents a debugger from attaching and tracing.
      You can check if the sysctl orptrace function is being imported (but the malware could import it dynamically)
      As noted in this writeup, “Defeating Anti-Debug Techniques: macOS ptrace variants” : “The message Process # exited with status = 45 (0x0000002d) is usually a tell-tale sign that the debug target is using PT_DENY_ATTACH

Fuzzing

ReportCrash analyzes crashing processes and saves a crash report to disk. A crash report contains information that can help a developer diagnose the cause of a crash. For applications and other processes running in the per-user launchd context, ReportCrash runs as a LaunchAgent and saves crash reports in the user's ~/Library/Logs/DiagnosticReports/ For daemons, other processes running in the system launchd context and other privileged processes, ReportCrash runs as a LaunchDaemon and saves crash reports in the system's /Library/Logs/DiagnosticReports
If you are worried about crash reports being sent to Apple you can disable them. If not, crash reports can be useful to figure out how a server crashed.
1
#To disable crash reporting:
2
launchctl unload -w /System/Library/LaunchAgents/com.apple.ReportCrash.plist
3
sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.ReportCrash.Root.plist
4
5
#To re-enable crash reporting:
6
launchctl load -w /System/Library/LaunchAgents/com.apple.ReportCrash.plist
7
sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.ReportCrash.Root.plist
Copied!

Sleep

While fuzzing in a MacOS it's important to not allow the Mac to sleep:

SSH Disconnect

If you are fuzzing via a SSH connection it's important to make sure the session isn't going to day. So change the sshd_config file with:
    TCPKeepAlive Yes
    ClientAliveInterval 0
    ClientAliveCountMax 0
1
sudo launchctl unload /System/Library/LaunchDaemons/ssh.plist
2
sudo launchctl load -w /System/Library/LaunchDaemons/ssh.plist
Copied!

Internal Handlers

Checkout this section to find out how you can find which app is responsible of handling the specified scheme or protocol.

Enumerating Network Processes

This interesting to find processes that are managing network data:
1
dtrace -n 'syscall::recv*:entry { printf("-> %s (pid=%d)", execname, pid); }' >> recv.log
2
#wait some time
3
sort -u recv.log > procs.txt
4
cat procs.txt
Copied!
Or use netstat or lsof

More Fuzzing MacOS Info

References

Last modified 2mo ago