You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardexpand all lines: macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-ipc-inter-process-communication/README.md
Copy file name to clipboardexpand all lines: macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-ipc-inter-process-communication/macos-mig-mach-interface-generator.md
Several new files will be created in the current directory.
68
68
69
+
{% hint style="success" %}
70
+
You can find a more complex example in your system with: `mdfind mach_port.defs`\
71
+
And you can compile it from the same folder as the file with: `mig -DLIBSYSCALL_INTERFACE mach_ports.defs`
72
+
{% endhint %}
73
+
69
74
In the files **`myipcServer.c`** and **`myipcServer.h`** you can find the declaration and definition of the struct **`SERVERPREFmyipc_subsystem`**, which basically defines the function to call based on the received message ID (we indicated a starting number of 500):
In this example we have only defined 1 function in the definitions, but if we would have defined more functions, they would have been inside the array of **`SERVERPREFmyipc_subsystem`** and the first one would have been assigned to the ID **500**, the second one to the ID **501**...
124
129
125
-
Actually it's possible to identify this relation in the struct **`subsystem_to_name_map_myipc`** from **`myipcServer.h`**:
130
+
If the function was expected to send a **reply** the function `mig_internal kern_return_t __MIG_check__Reply__<name>` would also exist.
131
+
132
+
Actually it's possible to identify this relation in the struct **`subsystem_to_name_map_myipc`** from **`myipcServer.h`** (**`subsystem_to_name_map_***`** in other files):
126
133
127
134
```c
128
135
#ifndef subsystem_to_name_map_myipc
@@ -167,7 +174,7 @@ Finally, another important function to make the server work will be **`myipc_ser
167
174
168
175
Check the previously highlighted lines accessing the function to call by ID.
169
176
170
-
In the following is the code to create a simple **server** and **client** where the client can call the functions Subtract from the server:
177
+
The following is the code to create a simple **server** and **client** where the client can call the functions Subtract from the server:
171
178
172
179
{% tabs %}
173
180
{% tab title="myipc_server.c" %}
@@ -231,7 +238,19 @@ int main() {
231
238
{% endtab %}
232
239
{% endtabs %}
233
240
234
-
### Binary Analysis
241
+
### The NDR\_record
242
+
243
+
The NDR\_record is exported by `libsystem_kernel.dylib`, and it's a struct that allows MIG to **transform data so it's agnostic of the system** it's being used as MIG was thought to be used between different systems (and not only in the same machine).
244
+
245
+
This is interesting because if `_NDR_record` is found in a binary as a dependency (`jtool2 -S <binary> | grep NDR` or `nm`), it means that the binary is a MIG client or Server.
246
+
247
+
Moreover **MIG servers** have the dispatch table in `__DATA.__const` (or in `__CONST.__constdata` in macOS kernel and `__DATA_CONST.__const` in other \*OS kernels). This can be dumped with **`jtool2`**.
248
+
249
+
And **MIG clients** will use the `__NDR_record` to send with `__mach_msg` to the servers.
250
+
251
+
## Binary Analysis
252
+
253
+
### jtool
235
254
236
255
As many binaries now use MIG to expose mach ports, it's interesting to know how to **identify that MIG was used** and the **functions that MIG executes** with each message ID.
237
256
@@ -241,6 +260,14 @@ As many binaries now use MIG to expose mach ports, it's interesting to know how
241
260
jtool2 -d __DATA.__const myipc_server | grep MIG
242
261
```
243
262
263
+
Moreover, MIG functions are just wrappers of the actual function that gets called, which means taht getting its dissasembly and grepping for BL you might be able to find the acatual function being called:
264
+
265
+
```bash
266
+
jtool2 -d __DATA.__const myipc_server | grep BL
267
+
```
268
+
269
+
### Assembly
270
+
244
271
It was previously mentioned that the function that will take care of **calling the correct function depending on the received message ID** was `myipc_server`. However, you usually won't have the symbols of the binary (no functions names), so it's interesting to **check how it looks like decompiled** as it will always be very similar (the code of this function is independent from the functions exposed):
245
272
246
273
{% tabs %}
@@ -370,6 +397,14 @@ Actually if you go to the function **`0x100004000`** you will find the array of
370
397
371
398
This data can be extracted [**using this Hopper script**](https://github.com/knightsc/hopper/blob/master/scripts/MIG%20Detect.py).
372
399
400
+
### Debug
401
+
402
+
The code generated by MIG also calles `kernel_debug` to generate logs about operations on entry and exit. It's possible to check them using **`trace`** or **`kdv`**: `kdv all | grep MIG`
403
+
404
+
## References
405
+
406
+
*[\*OS Internals, Volume I, User Mode, Jonathan Levin](https://www.amazon.com/MacOS-iOS-Internals-User-Mode/dp/099105556X)
407
+
373
408
<details>
374
409
375
410
<summary><strong>Learn AWS hacking from zero to hero with</strong> <ahref="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
0 commit comments