function stdapi_net_socket_tcp_shutdown($req, &$pkt) { my_print("doing stdapi_net_socket_tcp_shutdown"); $cid_tlv = packet_get_tlv($req, TLV_TYPE_CHANNEL_ID); $c = get_channel_by_id($cid_tlv['value']); if ($c && $c['type'] == 'socket') { @socket_shutdown($c[0], $how); $ret = ERROR_SUCCESS; } else { $ret = ERROR_FAILURE; } return $ret; }
function read($resource, $len = null) { global $udp_host_map; # Max packet length is magic. If we're reading a pipe that has data but # isn't going to generate any more without some input, then reading less # than all bytes in the buffer or 8192 bytes, the next read will never # return. if (is_null($len)) { $len = 8192; } #my_print(sprintf("Reading from $resource which is a %s", get_rtype($resource))); $buff = ''; switch (get_rtype($resource)) { case 'socket': if (array_key_exists((int) $resource, $udp_host_map)) { my_print("Reading UDP socket"); list($host, $port) = $udp_host_map[(int) $resource]; socket_recvfrom($resource, $buff, $len, PHP_BINARY_READ, $host, $port); } else { my_print("Reading TCP socket"); $buff .= socket_read($resource, $len, PHP_BINARY_READ); } break; case 'stream': global $msgsock; # Calling select here should ensure that we never try to read from a socket # or pipe that doesn't currently have data. If that ever happens, the # whole php process will block waiting for data that may never come. # Unfortunately, selecting on pipes created with proc_open on Windows # always returns immediately. Basically, shell interaction in Windows # is hosed until this gets figured out. See https://dev.metasploit.com/redmine/issues/2232 $r = array($resource); my_print("Calling select to see if there's data on {$resource}"); while (true) { $cnt = stream_select($r, $w = NULL, $e = NULL, 0); # Stream is not ready to read, have to live with what we've gotten # so far if ($cnt === 0) { break; } # if stream_select returned false, something is wrong with the # socket or the syscall was interrupted or something. if ($cnt === false or feof($resource)) { my_print("Checking for failed read..."); if (empty($buff)) { my_print("---- EOF ON {$resource} ----"); $buff = false; } break; } $md = stream_get_meta_data($resource); dump_array($md); if ($md['unread_bytes'] > 0) { $buff .= fread($resource, $md['unread_bytes']); break; } else { #$len = 1; $tmp = fread($resource, $len); $buff .= $tmp; if (strlen($tmp) < $len) { break; } } if ($resource != $msgsock) { my_print("buff: '{$buff}'"); } $r = array($resource); } my_print(sprintf("Done with the big read loop on {$resource}, got %d bytes", strlen($buff))); break; default: # then this is possibly a closed channel resource, see if we have any # data from previous reads $cid = get_channel_id_from_resource($resource); $c = get_channel_by_id($cid); if ($c and $c['data']) { $buff = substr($c['data'], 0, $len); $c['data'] = substr($c['data'], $len); my_print("Aha! got some leftovers"); } else { my_print("Wtf don't know how to read from resource {$resource}, c: {$c}"); if (is_array($c)) { dump_array($c); } break; } } my_print(sprintf("Read %d bytes", strlen($buff))); return $buff; }
function channel_read($chan_id, $len) { $c = get_channel_by_id($chan_id); if ($c && is_resource($c[1])) { return read($c[1], $len); } else { return false; } }