0) { curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $postvars); } if ($verbose) { $f = tmpfile(); curl_setopt($ch, CURLOPT_VERBOSE, true); curl_setopt($ch, CURLOPT_STDERR, $f); } $tofile = is_resource($output) && (get_resource_type($output) === 'stream' || get_resource_type($output) === 'file'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); if ($tofile) curl_setopt($ch, CURLOPT_FILE, $output); curl_setopt($ch, CURLOPT_HEADERFUNCTION, function($curl, $header) use (&$headers) { $len = strlen($header); $header = explode(':', $header, 2); if (count($header) < 2) // ignore invalid headers return $len; $name = strtolower(trim($header[0])); if (!array_key_exists($name, $headers)) $headers[$name] = [trim($header[1])]; else $headers[$name][] = trim($header[1]); return $len; }); curl_setopt($ch, CURLOPT_HTTPHEADER, $headerQuery); if ($tofile) curl_exec($ch); else $output = curl_exec($ch); curl_close($ch); if ($verbose) { fseek($f, 0); echo fread($f, 32*1024); fclose($f); } } function dump_query($name, $headers, $output) { print 'Performed: ' . $name . PHP_EOL; foreach ($headers as $name => $value) { print $name . ': ' . $value[0] . PHP_EOL; } print PHP_EOL . 'Output:' . PHP_EOL; print $output . PHP_EOL; } function setup_session() { $headersReq = [ 'Host: osrecovery.apple.com', 'Connection: close', 'User-Agent: InternetRecovery/1.0' ]; $output = ''; $headers = []; run_query($headersReq, 'http://osrecovery.apple.com/', $headers, $output); dump_query('setup_session', $headers, $output); $cookie = ''; foreach ($headers as $name => $value) { if ($name == 'set-cookie') { $cookie = explode(';', $value[0])[0]; break; } } return $cookie; } function obtain_images($session, $board, $mlb, $diag = false) { $headersReq = [ 'Host: osrecovery.apple.com', 'Connection: close', 'User-Agent: InternetRecovery/1.0', 'Cookie: ' . $session, 'Content-Type: text/plain', 'Expect:' ]; $output = ''; $headers = []; $postvars = 'cid=F4FDBCCF36190DD4' . PHP_EOL . // MLB, board serial number 'sn=' . $mlb . PHP_EOL . // board-id 'bid=' . $board . PHP_EOL . 'k=6E7D753C11E1F9652B99D3DB8C80A49E82143EA027CBA516E3E18B3A4FFDCD58' . PHP_EOL . 'fg=80F6E802A09B8B553202EE0D37AE64662ACFAF30B111E1984C01F64551BB7EFE' ; $images = [ 'image' => [], 'chunklist' => [] ]; if ($diag) { run_query($headersReq, 'http://osrecovery.apple.com/InstallationPayload/Diagnostics', $headers, $output, $postvars); } else { run_query($headersReq, 'http://osrecovery.apple.com/InstallationPayload/RecoveryImage', $headers, $output, $postvars); } dump_query('obtain_images', $headers, $output); $fields = explode("\n", $output); foreach ($fields as $field) { $pair = explode(': ', $field); if (count($pair) != 2) continue; $name = $pair[0]; $value = $pair[1]; if ($name == 'AU') $images['image']['link'] = $value; else if ($name == 'AH') $images['image']['hash'] = $value; else if ($name == 'AT') $images['image']['cookie'] = $value; else if ($name == 'CU') $images['chunklist']['link'] = $value; else if ($name == 'CH') $images['chunklist']['hash'] = $value; else if ($name == 'CT') $images['chunklist']['cookie'] = $value; } return $images; } function download_images($images, $diag = false) { foreach ($images as $imagename => $imagefields) { $headersReq = [ 'Host: ' . parse_url($imagefields['link'], PHP_URL_HOST), 'Connection: close', 'User-Agent: InternetRecovery/1.0', 'Cookie: AssetToken=' . $imagefields['cookie'] ]; if ($diag) $type = 'Diagnostics'; else $type = 'Recovery'; if ($imagename == 'image') $filename = $type . 'Image.dmg'; else $filename = $type . 'Image.chunklist'; $headers = []; $output = fopen($filename, 'w+'); print $imagefields['link'] . ' ' . $filename . PHP_EOL; run_query($headersReq, $imagefields['link'], $headers, $output); fclose($output); } } if ($argc < 2) { print 'Usage: php obtain_recovery.php board-id [MLB] [--diag]' . PHP_EOL; exit(1); } $board = $argv[1]; $mlb = '00000000000000000'; $diag = false; if ($argc > 2) { if ($argv[2] == '--diag') { $diag = true; } else { $mlb = $argv[2]; $diag = $argc > 3 && $argv[3] == '--diag'; } } $sess = setup_session(); if ($sess == '') { print 'Failed to obtain session!' . PHP_EOL; exit(1); } $images = obtain_images($sess, $board, $mlb, $diag); if (count($images['image']) == 0 || count($images['chunklist']) == 0) { print 'Failed to obtain images!' . PHP_EOL; exit(1); } download_images($images, $diag);