| name | macos-mig-analyzer |
| description | Analyze Mach Interface Generator (MIG) IPC on macOS. Use this skill whenever the user mentions MIG, Mach IPC, macOS inter-process communication, binary analysis of Mach-O files with IPC, extracting dispatch tables from macOS binaries, or reverse engineering macOS system services. Trigger for any task involving .defs files, mach_port, bootstrap_look_up, jtool2 MIG analysis, or identifying RPC functions in macOS binaries. |
macOS MIG Analyzer
A skill for analyzing Mach Interface Generator (MIG) based inter-process communication on macOS systems.
When to Use This Skill
Use this skill when:
- Analyzing macOS binaries that use Mach IPC
- Reverse engineering MIG-based system services
- Extracting dispatch tables from Mach-O binaries
- Understanding
.defs interface definition files
- Identifying RPC functions in macOS daemons
- Debugging Mach port communication
- Using
jtool2 to parse MIG information
MIG Fundamentals
MIG (Mach Interface Generator) simplifies Mach IPC code creation by generating server and client code from Interface Definition Language (IDL) files with .defs extension.
Definition File Structure
MIG definitions have 5 sections:
- Subsystem declaration: Specifies name and ID, optionally marked as
KernelServer
- Inclusions and imports: Uses C-preprocessor, supports
uimport and simport
- Type declarations: Custom types with
[in/out]tran, c[user/server]type, destructor
- Operations: RPC method definitions (5 types:
routine, simpleroutine, procedure, simpleprocedure, function)
- Generated code: Server and client stubs
Operation Types
| Type | Expects Reply |
|---|
routine | Yes |
simpleroutine | No |
procedure | Yes |
simpleprocedure | No |
function | Yes |
Binary Analysis Workflow
Step 1: Identify MIG Usage
Check if a binary uses MIG by looking for _NDR_record dependency:
jtool2 -S <binary> | grep NDR
nm <binary> | grep NDR
MIG servers have dispatch tables in __DATA.__const (macOS userland) or __CONST.__constdata (kernel).
Step 2: Extract MIG Dispatch Information
Use jtool2 to parse MIG data from the binary:
jtool2 -d __DATA.__const <binary> | grep MIG
jtool2 -d __DATA.__const <binary> | grep BL
Step 3: Locate Routine Descriptors
The dispatch table contains routine_descriptor structs (0x28 bytes each):
struct routine_descriptor {
mig_impl_routine_t impl_routine;
mig_stub_routine_t stub_routine;
int const_count;
int var_count;
routine_arg_descriptor_t *arg_desc;
mach_msg_size_t maxsize;
};
Each descriptor is 0x28 bytes. The first 8 bytes contain the function address.
Step 4: Map Message IDs to Functions
MIG uses sequential IDs starting from the subsystem ID:
msgh_id = InHeadP->msgh_id - 500;
routine = subsystem.routine[msgh_id].stub_routine;
Step 5: Analyze Server Routine
The myipc_server function (or similar) handles message dispatch. Key patterns:
- Validates message ID range
- Calculates array index:
msgh_id - start_id
- Looks up function pointer in dispatch table
- Calls the appropriate handler
Look for this pattern in decompiled code:
if (msgh_id >= start && msgh_id <= end) {
routine = dispatch_table[msgh_id - start].stub_routine;
if (routine != 0) {
routine(InHeadP, OutHeadP);
return TRUE;
}
}
Common Analysis Tasks
Extract All MIG Functions from Binary
jtool2 -s <binary> | grep -A5 "__DATA.__const"
jtool2 -d __DATA.__const <binary> > mig_dump.txt
grep -A20 "subsystem" mig_dump.txt
Find Bootstrap Service Names
MIG servers often register with bootstrap:
jtool2 -s <binary> | grep -i bootstrap
strings <binary> | grep -E "^[a-z0-9._-]+$" | grep -v "^[0-9]"
Identify Client vs Server
| Indicator | Client | Server |
|---|
Uses __NDR_record | Yes | Yes |
Calls __mach_msg | Yes | Yes |
| Has dispatch table | No | Yes |
Uses bootstrap_look_up | Yes | No |
Uses bootstrap_check_in | No | Yes |
Has mach_msg_server | No | Yes |
Debugging MIG Communication
Enable MIG debug logging:
kdv all | grep MIG
trace -f <binary>
Example Analysis
Simple MIG Definition
subsystem myipc 500;
userprefix USERPREF;
serverprefix SERVERPREF;
#include <mach/mach_types.defs>
#include <mach/std_types.defs>
simpleroutine Subtract(
server_port : mach_port_t;
n1 : uint32_t;
n2 : uint32_t);
Generated Server Structure
const struct SERVERPREFmyipc_subsystem SERVERPREFmyipc_subsystem = {
myipc_server_routine,
500,
501,
sizeof(union __ReplyUnion__),
0,
{
{ 0, _XSubtract, 3, 0, 0, sizeof(__Reply__Subtract_t) }
}
};
Server Implementation Pattern
kern_return_t SERVERPREFSubtract(mach_port_t server_port, uint32_t n1, uint32_t n2)
{
printf("Received: %d - %d = %d\n", n1, n2, n1 - n2);
return KERN_SUCCESS;
}
int main() {
mach_port_t port;
kern_return_t kr;
kr = bootstrap_check_in(bootstrap_port, "com.example.service", &port);
mach_msg_server(myipc_server, sizeof(union __RequestUnion__), port, MACH_MSG_TIMEOUT_NONE);
}
Client Implementation Pattern
int main() {
mach_port_t port;
kern_return_t kr;
kr = bootstrap_look_up(bootstrap_port, "com.example.service", &port);
if (kr != KERN_SUCCESS) {
printf("Failed to lookup service\n");
return 1;
}
USERPREFSubtract(port, 40, 2);
}
Tools Reference
jtool2 Commands
jtool2 -s <binary>
jtool2 -d <section> <binary>
jtool2 -S <binary>
jtool2 -D <binary>
Finding MIG Examples on System
mdfind "*.defs"
mdfind mach_port.defs
mig -DLIBSYSCALL_INTERFACE mach_ports.defs
Common Pitfalls
- Message ID offset: Remember to subtract the subsystem start ID when indexing into the dispatch table
- Reply handling: Only
routine, procedure, and function types expect replies
- Port management: First argument is always the server port; MIG handles reply ports automatically
- NDR encoding: Data is encoded for cross-system compatibility via
_NDR_record
- Dispatch table location: Varies by platform (
__DATA.__const vs __CONST.__constdata)
Next Steps
For deeper analysis:
- Use Hopper/IDA to decompile the server routine
- Extract routine descriptors using the 0x28-byte stride
- Map each function address to its handler
- Trace actual IPC calls with
dtrace or kdv
- Compare against known system services for patterns
References
- OS Internals, Volume I, User Mode - Jonathan Levin
- macOS Mach IPC documentation
- jtool2 GitHub repository
- MIG man page:
man mig