mirror of
https://github.com/rapid7/metasploit-payloads
synced 2025-04-06 01:16:37 +02:00
Merge branch 'master' into winhttp
This commit is contained in:
commit
b7d6eba46b
c/meterpreter
source
extensions
networkpug
sniffer
stdapi
server
workspace/ext_server_stdapi
@ -76,7 +76,7 @@ void packet_handler(u_char *user, const struct pcap_pkthdr *h, const u_char *byt
|
||||
}
|
||||
np->packet_stream = tmp;
|
||||
|
||||
size = (unsigned short int *)(np->packet_stream + np->packet_stream_length);
|
||||
size = (unsigned short int *)(np->packet_stream + np->packet_stream_length);
|
||||
*size = htons(h->caplen);
|
||||
data = (unsigned char *)(np->packet_stream + np->packet_stream_length + 2);
|
||||
|
||||
@ -438,7 +438,11 @@ Command customCommands[] =
|
||||
/*
|
||||
* Initialize the server extension
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
DWORD __declspec(dllexport) InitServerExtension(Remote *remote)
|
||||
#else
|
||||
DWORD InitServerExtension(Remote *remote)
|
||||
#endif
|
||||
{
|
||||
int peername_len;
|
||||
struct sockaddr peername;
|
||||
@ -497,7 +501,11 @@ DWORD __declspec(dllexport) InitServerExtension(Remote *remote)
|
||||
/*
|
||||
* Deinitialize the server extension
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
DWORD __declspec(dllexport) DeinitServerExtension(Remote *remote)
|
||||
#else
|
||||
DWORD DeinitServerExtension(Remote *remote)
|
||||
#endif
|
||||
{
|
||||
command_deregister_all(customCommands);
|
||||
|
||||
@ -507,3 +515,23 @@ DWORD __declspec(dllexport) DeinitServerExtension(Remote *remote)
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Get the name of the extension.
|
||||
* @param buffer Pointer to the buffer to write the name to.
|
||||
* @param bufferSize Size of the \c buffer parameter.
|
||||
* @return Indication of success or failure.
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
DWORD __declspec(dllexport) GetExtensionName(char* buffer, int bufferSize)
|
||||
#else
|
||||
DWORD GetExtensionName(char* buffer, int bufferSize)
|
||||
#endif
|
||||
{
|
||||
#ifdef _WIN32
|
||||
strncpy_s(buffer, bufferSize, "networkpug", bufferSize - 1);
|
||||
#else
|
||||
strncpy(buffer, "networkpug", bufferSize - 1);
|
||||
#endif
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
@ -1197,7 +1197,11 @@ DWORD request_sniffer_capture_dump(Remote *remote, Packet *packet)
|
||||
* @param remote Pointer to the remote instance.
|
||||
* @return Indication of success or failure.
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
DWORD __declspec(dllexport) InitServerExtension(Remote *remote)
|
||||
#else
|
||||
DWORD InitServerExtension(Remote *remote)
|
||||
#endif
|
||||
{
|
||||
#ifdef _WIN32
|
||||
// This handle has to be set before calls to command_register
|
||||
@ -1271,7 +1275,11 @@ DWORD __declspec(dllexport) InitServerExtension(Remote *remote)
|
||||
* @param remote Pointer to the remote instance.
|
||||
* @return Indication of success or failure.
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
DWORD __declspec(dllexport) DeinitServerExtension(Remote *remote)
|
||||
#else
|
||||
DWORD DeinitServerExtension(Remote *remote)
|
||||
#endif
|
||||
{
|
||||
command_register_all( customCommands );
|
||||
|
||||
@ -1294,8 +1302,16 @@ DWORD __declspec(dllexport) DeinitServerExtension(Remote *remote)
|
||||
* @param bufferSize Size of the \c buffer parameter.
|
||||
* @return Indication of success or failure.
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
DWORD __declspec(dllexport) GetExtensionName(char* buffer, int bufferSize)
|
||||
#else
|
||||
DWORD GetExtensionName(char* buffer, int bufferSize)
|
||||
#endif
|
||||
{
|
||||
#ifdef _WIN32
|
||||
strncpy_s(buffer, bufferSize, "sniffer", bufferSize - 1);
|
||||
#else
|
||||
strncpy(buffer, "sniffer", bufferSize - 1);
|
||||
#endif
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
@ -1,370 +1,132 @@
|
||||
#include "precomp.h"
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <dirent.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Gets the contents of a given directory path and returns the list of file
|
||||
* names to the requestor.
|
||||
*
|
||||
* TLVs:
|
||||
*
|
||||
* req: TLV_TYPE_DIRECTORY_PATH - The directory that should be listed
|
||||
*/
|
||||
DWORD request_fs_ls(Remote *remote, Packet *packet)
|
||||
{
|
||||
Packet *response = packet_create_response(packet);
|
||||
LPCSTR directory;
|
||||
DWORD result = ERROR_SUCCESS;
|
||||
LPSTR expanded = NULL, tempFile = NULL;
|
||||
size_t tempFileSize = 0;
|
||||
LPSTR baseDirectory = NULL;
|
||||
struct meterp_stat buf;
|
||||
|
||||
directory = packet_get_tlv_value_string(packet, TLV_TYPE_DIRECTORY_PATH);
|
||||
|
||||
// Enumerate the directory if one was provided
|
||||
if (!directory)
|
||||
result = ERROR_INVALID_PARAMETER;
|
||||
else
|
||||
{
|
||||
#ifdef _WIN32
|
||||
WIN32_FIND_DATA data;
|
||||
HANDLE ctx = NULL;
|
||||
#else
|
||||
DIR *ctx;
|
||||
struct dirent *data;
|
||||
#endif
|
||||
BOOLEAN freeDirectory = FALSE;
|
||||
LPSTR tempDirectory = (LPSTR)directory;
|
||||
|
||||
#ifdef _WIN32
|
||||
// If there is not wildcard mask on the directory, create a version of the
|
||||
// directory with a mask appended
|
||||
if (!strrchr(directory, '*'))
|
||||
{
|
||||
if (!(tempDirectory = (LPSTR)malloc(strlen(directory) + 3)))
|
||||
{
|
||||
result = ERROR_NOT_ENOUGH_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
sprintf(tempDirectory, "%s\\*", directory);
|
||||
|
||||
// Dupe!
|
||||
if (!(baseDirectory = _strdup(directory)))
|
||||
{
|
||||
result = ERROR_NOT_ENOUGH_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
// Otherwise, if it does have an asterisk, we need to scan back and find
|
||||
// the base directory. If there is no slash, it means we're listing the
|
||||
// cwd.
|
||||
else
|
||||
{
|
||||
PCHAR slash = strrchr(directory, '\\');
|
||||
|
||||
if (slash)
|
||||
{
|
||||
*slash = 0;
|
||||
|
||||
if (!(baseDirectory = _strdup(directory)))
|
||||
{
|
||||
result = ERROR_NOT_ENOUGH_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
*slash = '\\';
|
||||
}
|
||||
}
|
||||
|
||||
// Expand the path
|
||||
if (!(expanded = fs_expand_path(tempDirectory)))
|
||||
{
|
||||
result = ERROR_NOT_ENOUGH_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
// Start the find operation
|
||||
ctx = FindFirstFile(expanded, &data);
|
||||
|
||||
#define DF_NAME data.cFileName
|
||||
#else
|
||||
expanded = 0;
|
||||
ctx = opendir(tempDirectory);
|
||||
if(ctx == NULL)
|
||||
{
|
||||
result = errno;
|
||||
goto out;
|
||||
}
|
||||
data = readdir(ctx);
|
||||
if (!(baseDirectory = _strdup(directory)))
|
||||
{
|
||||
result = ERROR_NOT_ENOUGH_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
#define DF_NAME data->d_name
|
||||
#endif
|
||||
|
||||
do
|
||||
{
|
||||
size_t fullSize = (baseDirectory ? strlen(baseDirectory) : 0) + strlen(DF_NAME) + 2;
|
||||
|
||||
// No context? Sucktastic
|
||||
if (ctx == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
result = GetLastError();
|
||||
break;
|
||||
}
|
||||
|
||||
// Allocate temporary storage to stat the file
|
||||
if ((!tempFile) || (tempFileSize < fullSize))
|
||||
{
|
||||
if (tempFile)
|
||||
{
|
||||
free(tempFile);
|
||||
}
|
||||
|
||||
// No memory means we suck a lot like spoon's mom
|
||||
if (!(tempFile = (LPSTR)malloc(fullSize)))
|
||||
{
|
||||
result = ERROR_NOT_ENOUGH_MEMORY;
|
||||
break;
|
||||
}
|
||||
|
||||
// Update the tempFileSize so that we don't allocate if we don't
|
||||
// need to like a true efficient ninja
|
||||
tempFileSize = fullSize;
|
||||
}
|
||||
|
||||
// Build the full path
|
||||
if (baseDirectory)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
sprintf(tempFile, "%s\\%s", baseDirectory, DF_NAME);
|
||||
#else
|
||||
sprintf(tempFile, "%s/%s", baseDirectory, DF_NAME);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(tempFile, "%s", DF_NAME);
|
||||
}
|
||||
|
||||
// Add the file name to the response
|
||||
packet_add_tlv_string(response, TLV_TYPE_FILE_NAME, DF_NAME);
|
||||
// Add the full path
|
||||
packet_add_tlv_string(response, TLV_TYPE_FILE_PATH, tempFile);
|
||||
|
||||
// Stat the file to get more information about it.
|
||||
if (fs_stat(tempFile, &buf) >= 0)
|
||||
{
|
||||
packet_add_tlv_raw(response, TLV_TYPE_STAT_BUF, &buf, sizeof(buf));
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
} while (FindNextFile(ctx, &data));
|
||||
#else
|
||||
} while (data = readdir(ctx));
|
||||
#endif
|
||||
#undef DF_NAME
|
||||
|
||||
// Clean up resources
|
||||
if (freeDirectory)
|
||||
{
|
||||
free(tempDirectory);
|
||||
}
|
||||
|
||||
if (ctx)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
FindClose(ctx);
|
||||
#else
|
||||
closedir(ctx);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (expanded)
|
||||
{
|
||||
free(expanded);
|
||||
}
|
||||
|
||||
out:
|
||||
if (baseDirectory)
|
||||
{
|
||||
free(baseDirectory);
|
||||
}
|
||||
|
||||
// Set the result and transmit the response
|
||||
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
|
||||
|
||||
packet_transmit(remote, response, NULL);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets the current working directory
|
||||
*/
|
||||
DWORD request_fs_getwd(Remote *remote, Packet *packet)
|
||||
{
|
||||
Packet *response = packet_create_response(packet);
|
||||
DWORD directorySize = 4096, realSize;
|
||||
LPSTR directory = NULL;
|
||||
DWORD result = ERROR_SUCCESS;
|
||||
|
||||
do
|
||||
{
|
||||
again:
|
||||
// Allocate storage for the directory path
|
||||
if (!(directory = (LPSTR)malloc(directorySize)))
|
||||
{
|
||||
result = ERROR_NOT_ENOUGH_MEMORY;
|
||||
break;
|
||||
}
|
||||
|
||||
memset(directory, 0, directorySize);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (!(realSize = GetCurrentDirectory(directorySize, directory)))
|
||||
{
|
||||
result = ERROR_NOT_ENOUGH_MEMORY;
|
||||
break;
|
||||
}
|
||||
else if (realSize > directorySize)
|
||||
{
|
||||
free(directory);
|
||||
directorySize = realSize;
|
||||
goto again;
|
||||
}
|
||||
#else
|
||||
if (!getcwd(directory, directorySize))
|
||||
{
|
||||
if (errno == ERANGE && directorySize > 0)
|
||||
{
|
||||
// Then we didn't allocate enough to hold the whole path,
|
||||
// increase the size and try again.
|
||||
free(directory);
|
||||
directorySize = directorySize * 2;
|
||||
goto again;
|
||||
} else {
|
||||
dprintf("getcwd failed with errno %d", errno);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
packet_add_tlv_string(response, TLV_TYPE_DIRECTORY_PATH,
|
||||
directory);
|
||||
|
||||
} while (0);
|
||||
|
||||
// Set the result and transmit the response
|
||||
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
|
||||
|
||||
packet_transmit(remote, response, NULL);
|
||||
|
||||
if (directory)
|
||||
free(directory);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Changes the working directory of the process
|
||||
*
|
||||
* TLVs:
|
||||
*
|
||||
* req: TLV_TYPE_DIRECTORY_PATH - The directory path to change the working
|
||||
* directory to.
|
||||
*/
|
||||
DWORD request_fs_chdir(Remote *remote, Packet *packet)
|
||||
{
|
||||
Packet *response = packet_create_response(packet);
|
||||
LPCSTR directory;
|
||||
DWORD result = ERROR_SUCCESS;
|
||||
|
||||
directory = packet_get_tlv_value_string(packet, TLV_TYPE_DIRECTORY_PATH);
|
||||
|
||||
if (!directory)
|
||||
result = ERROR_INVALID_PARAMETER;
|
||||
#ifdef _WIN32
|
||||
else if (!SetCurrentDirectory(directory))
|
||||
#else
|
||||
else if (chdir(directory))
|
||||
#endif
|
||||
result = GetLastError();
|
||||
|
||||
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
|
||||
|
||||
packet_transmit(remote, response, NULL);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates a new directory
|
||||
*
|
||||
* TLVs:
|
||||
*
|
||||
* req: TLV_TYPE_DIRECTORY_PATH - The directory path to create.
|
||||
*/
|
||||
DWORD request_fs_mkdir(Remote *remote, Packet *packet)
|
||||
{
|
||||
Packet *response = packet_create_response(packet);
|
||||
LPCSTR directory;
|
||||
DWORD result = ERROR_SUCCESS;
|
||||
|
||||
directory = packet_get_tlv_value_string(packet, TLV_TYPE_DIRECTORY_PATH);
|
||||
|
||||
if (!directory)
|
||||
result = ERROR_INVALID_PARAMETER;
|
||||
#ifdef _WIN32
|
||||
else if (!CreateDirectory(directory, NULL))
|
||||
#else
|
||||
else if (mkdir(directory, 0777))
|
||||
#endif
|
||||
result = GetLastError();
|
||||
|
||||
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
|
||||
|
||||
packet_transmit(remote, response, NULL);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Removes the supplied directory from disk if it's empty
|
||||
*
|
||||
* TLVs:
|
||||
*
|
||||
* req: TLV_TYPE_DIRECTORY_PATH - The directory that is to be removed.
|
||||
*/
|
||||
DWORD request_fs_delete_dir(Remote *remote, Packet *packet)
|
||||
{
|
||||
Packet *response = packet_create_response(packet);
|
||||
LPCSTR directory;
|
||||
DWORD result = ERROR_SUCCESS;
|
||||
|
||||
directory = packet_get_tlv_value_string(packet, TLV_TYPE_DIRECTORY_PATH);
|
||||
|
||||
if (!directory)
|
||||
result = ERROR_INVALID_PARAMETER;
|
||||
#ifdef _WIN32
|
||||
else if (!RemoveDirectory(directory))
|
||||
#else
|
||||
else if (rmdir(directory))
|
||||
#endif
|
||||
result = GetLastError();
|
||||
|
||||
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
|
||||
|
||||
packet_transmit(remote, response, NULL);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
#include "precomp.h"
|
||||
|
||||
#include "fs_local.h"
|
||||
|
||||
void request_fs_ls_cb(void *arg, char *name, char *short_name, char *path)
|
||||
{
|
||||
Packet *response = arg;
|
||||
struct meterp_stat s;
|
||||
|
||||
/*
|
||||
* Add the file name, full path and stat information
|
||||
*/
|
||||
packet_add_tlv_string(response, TLV_TYPE_FILE_NAME, name);
|
||||
packet_add_tlv_string(response, TLV_TYPE_FILE_PATH, path);
|
||||
if (short_name) {
|
||||
packet_add_tlv_string(response, TLV_TYPE_FILE_SHORT_NAME, short_name);
|
||||
}
|
||||
if (fs_stat(path, &s) >= 0) {
|
||||
packet_add_tlv_raw(response, TLV_TYPE_STAT_BUF, &s, sizeof(s));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets the contents of a given directory path and returns the list of file
|
||||
* names to the requestor.
|
||||
*
|
||||
* req: TLV_TYPE_DIRECTORY_PATH - The directory that should be listed
|
||||
*/
|
||||
DWORD request_fs_ls(Remote * remote, Packet * packet)
|
||||
{
|
||||
Packet *response = packet_create_response(packet);
|
||||
LPCSTR directory = packet_get_tlv_value_string(packet, TLV_TYPE_DIRECTORY_PATH);
|
||||
DWORD result;
|
||||
|
||||
if (!directory) {
|
||||
result = ERROR_INVALID_PARAMETER;
|
||||
} else {
|
||||
result = fs_ls(directory, request_fs_ls_cb, response);
|
||||
}
|
||||
|
||||
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
|
||||
return packet_transmit(remote, response, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets the current working directory
|
||||
*
|
||||
* req: TLV_TYPE_DIRECTORY_PATH - The directory path to change the working
|
||||
* directory to.
|
||||
*/
|
||||
DWORD request_fs_getwd(Remote * remote, Packet * packet)
|
||||
{
|
||||
Packet *response = packet_create_response(packet);
|
||||
char *directory = NULL;
|
||||
DWORD result;
|
||||
|
||||
result = fs_getwd(&directory);
|
||||
if (directory != NULL) {
|
||||
packet_add_tlv_string(response, TLV_TYPE_DIRECTORY_PATH, directory);
|
||||
free(directory);
|
||||
}
|
||||
|
||||
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
|
||||
return packet_transmit(remote, response, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Changes the working directory of the process
|
||||
*
|
||||
* req: TLV_TYPE_DIRECTORY_PATH - The directory path to change the working
|
||||
* directory to.
|
||||
*/
|
||||
DWORD request_fs_chdir(Remote * remote, Packet * packet)
|
||||
{
|
||||
Packet *response = packet_create_response(packet);
|
||||
char *directory;
|
||||
DWORD result;
|
||||
directory = packet_get_tlv_value_string(packet, TLV_TYPE_DIRECTORY_PATH);
|
||||
|
||||
if (directory == NULL) {
|
||||
result = ERROR_INVALID_PARAMETER;
|
||||
} else {
|
||||
result = fs_chdir(directory);
|
||||
}
|
||||
|
||||
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
|
||||
return packet_transmit(remote, response, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates a new directory
|
||||
*
|
||||
* req: TLV_TYPE_DIRECTORY_PATH - The directory path to create.
|
||||
*/
|
||||
DWORD request_fs_mkdir(Remote * remote, Packet * packet)
|
||||
{
|
||||
Packet *response = packet_create_response(packet);
|
||||
char *directory;
|
||||
DWORD result;
|
||||
directory = packet_get_tlv_value_string(packet, TLV_TYPE_DIRECTORY_PATH);
|
||||
|
||||
if (directory == NULL) {
|
||||
result = ERROR_INVALID_PARAMETER;
|
||||
} else {
|
||||
result = fs_mkdir(directory);
|
||||
}
|
||||
|
||||
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
|
||||
return packet_transmit(remote, response, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Removes the supplied directory from disk if it's empty
|
||||
*
|
||||
* req: TLV_TYPE_DIRECTORY_PATH - The directory that is to be removed.
|
||||
*/
|
||||
DWORD request_fs_delete_dir(Remote * remote, Packet * packet)
|
||||
{
|
||||
Packet *response = packet_create_response(packet);
|
||||
char *directory;
|
||||
DWORD result;
|
||||
directory = packet_get_tlv_value_string(packet, TLV_TYPE_DIRECTORY_PATH);
|
||||
|
||||
if (directory == NULL) {
|
||||
result = ERROR_INVALID_PARAMETER;
|
||||
} else {
|
||||
result = fs_delete_dir(directory);
|
||||
}
|
||||
|
||||
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
|
||||
return packet_transmit(remote, response, NULL);
|
||||
}
|
||||
|
@ -1,4 +1,6 @@
|
||||
#include "precomp.h"
|
||||
#include "fs_local.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <openssl/md5.h>
|
||||
@ -23,19 +25,18 @@ static DWORD file_channel_write(Channel *channel, Packet *request,
|
||||
{
|
||||
FileContext *ctx = (FileContext *)context;
|
||||
DWORD result= ERROR_SUCCESS;
|
||||
DWORD written = 0;
|
||||
size_t written = 0;
|
||||
|
||||
// Write a chunk
|
||||
if (bufferSize && (written = (DWORD)fwrite(buffer, 1, bufferSize, ctx->fd)) <= 0)
|
||||
{
|
||||
written = 0;
|
||||
result = GetLastError();
|
||||
if (bufferSize) {
|
||||
written = fwrite(buffer, 1, bufferSize, ctx->fd);
|
||||
if (written < bufferSize) {
|
||||
result = GetLastError();
|
||||
}
|
||||
}
|
||||
|
||||
// Set bytesWritten
|
||||
if (bytesWritten)
|
||||
{
|
||||
*bytesWritten = written;
|
||||
if (bytesWritten) {
|
||||
*bytesWritten = (DWORD)written;
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -64,18 +65,19 @@ static DWORD file_channel_read(Channel *channel, Packet *request,
|
||||
{
|
||||
FileContext *ctx = (FileContext *)context;
|
||||
DWORD result = ERROR_SUCCESS;
|
||||
DWORD bytes = 0;
|
||||
size_t bytes = 0;
|
||||
|
||||
// Read a chunk
|
||||
if (bufferSize && (bytes= (DWORD)fread(buffer, 1, bufferSize, ctx->fd)) <= 0)
|
||||
{
|
||||
bytes = 0;
|
||||
result = GetLastError();
|
||||
if (bufferSize) {
|
||||
bytes = fread(buffer, 1, bufferSize, ctx->fd);
|
||||
if (bytes < bufferSize) {
|
||||
result = GetLastError();
|
||||
}
|
||||
}
|
||||
|
||||
// Set bytesRead
|
||||
if (bytesRead)
|
||||
*bytesRead = bytes;
|
||||
if (bytesRead) {
|
||||
*bytesRead = (DWORD)bytes;
|
||||
}
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
@ -112,8 +114,9 @@ static DWORD file_channel_tell(Channel *channel, Packet *request,
|
||||
DWORD result = ERROR_SUCCESS;
|
||||
LONG pos = 0;
|
||||
|
||||
if ((pos = ftell(ctx->fd)) < 0)
|
||||
if ((pos = ftell(ctx->fd)) < 0) {
|
||||
result = GetLastError();
|
||||
}
|
||||
|
||||
if (offset)
|
||||
*offset = pos;
|
||||
@ -136,90 +139,64 @@ DWORD request_fs_file_channel_open(Remote *remote, Packet *packet)
|
||||
FileContext *ctx;
|
||||
LPSTR expandedFilePath = NULL;
|
||||
|
||||
do
|
||||
{
|
||||
// Allocate a response
|
||||
response = packet_create_response(packet);
|
||||
// Allocate a response
|
||||
response = packet_create_response(packet);
|
||||
|
||||
// Get the channel flags
|
||||
flags = packet_get_tlv_value_uint(packet, TLV_TYPE_FLAGS);
|
||||
// Get the channel flags
|
||||
flags = packet_get_tlv_value_uint(packet, TLV_TYPE_FLAGS);
|
||||
|
||||
// Allocate storage for the file context
|
||||
if (!(ctx = (FileContext *)malloc(sizeof(FileContext))))
|
||||
{
|
||||
res = ERROR_NOT_ENOUGH_MEMORY;
|
||||
break;
|
||||
}
|
||||
// Allocate storage for the file context
|
||||
if (!(ctx = calloc(1, sizeof(FileContext)))) {
|
||||
res = ERROR_NOT_ENOUGH_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
// Get the file path and the mode
|
||||
filePath = packet_get_tlv_value_string(packet, TLV_TYPE_FILE_PATH);
|
||||
mode = packet_get_tlv_value_string(packet, TLV_TYPE_FILE_MODE);
|
||||
// Get the file path and the mode
|
||||
filePath = packet_get_tlv_value_string(packet, TLV_TYPE_FILE_PATH);
|
||||
mode = packet_get_tlv_value_string(packet, TLV_TYPE_FILE_MODE);
|
||||
|
||||
// No file path? bogus.
|
||||
if (!filePath)
|
||||
{
|
||||
res = ERROR_INVALID_PARAMETER;
|
||||
break;
|
||||
}
|
||||
if (mode == NULL) {
|
||||
mode = "rb";
|
||||
}
|
||||
|
||||
// Expand the file path
|
||||
if (!(expandedFilePath = fs_expand_path(filePath)))
|
||||
{
|
||||
res = ERROR_NOT_ENOUGH_MEMORY;
|
||||
break;
|
||||
}
|
||||
res = fs_fopen(filePath, mode, &ctx->fd);
|
||||
if (res != ERROR_SUCCESS) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!mode)
|
||||
mode = "rb";
|
||||
memset(&chops, 0, sizeof(chops));
|
||||
|
||||
// Invalid file?
|
||||
if (!(ctx->fd = fopen(expandedFilePath, mode)))
|
||||
{
|
||||
res = GetLastError();
|
||||
break;
|
||||
}
|
||||
// Initialize the pool operation handlers
|
||||
chops.native.context = ctx;
|
||||
chops.native.write = file_channel_write;
|
||||
chops.native.close = file_channel_close;
|
||||
chops.read = file_channel_read;
|
||||
chops.eof = file_channel_eof;
|
||||
chops.seek = file_channel_seek;
|
||||
chops.tell = file_channel_tell;
|
||||
|
||||
memset(&chops, 0, sizeof(chops));
|
||||
// Check the response allocation & allocate a un-connected
|
||||
// channel
|
||||
if ((!response) || (!(newChannel = channel_create_pool(0, flags, &chops)))) {
|
||||
res = ERROR_NOT_ENOUGH_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
// Initialize the pool operation handlers
|
||||
chops.native.context = ctx;
|
||||
chops.native.write = file_channel_write;
|
||||
chops.native.close = file_channel_close;
|
||||
chops.read = file_channel_read;
|
||||
chops.eof = file_channel_eof;
|
||||
chops.seek = file_channel_seek;
|
||||
chops.tell = file_channel_tell;
|
||||
|
||||
// Check the response allocation & allocate a un-connected
|
||||
// channel
|
||||
if ((!response) || (!(newChannel = channel_create_pool(0, flags, &chops))))
|
||||
{
|
||||
res = ERROR_NOT_ENOUGH_MEMORY;
|
||||
break;
|
||||
}
|
||||
|
||||
// Add the channel identifier to the response
|
||||
packet_add_tlv_uint(response, TLV_TYPE_CHANNEL_ID,
|
||||
channel_get_id(newChannel));
|
||||
|
||||
} while (0);
|
||||
// Add the channel identifier to the response
|
||||
packet_add_tlv_uint(response, TLV_TYPE_CHANNEL_ID, channel_get_id(newChannel));
|
||||
|
||||
out:
|
||||
// Transmit the packet if it's valid
|
||||
packet_transmit_response(res, remote, response);
|
||||
|
||||
// Clean up on failure
|
||||
if (res != ERROR_SUCCESS)
|
||||
{
|
||||
if (newChannel)
|
||||
if (res != ERROR_SUCCESS) {
|
||||
if (newChannel) {
|
||||
channel_destroy(newChannel, NULL);
|
||||
if (ctx)
|
||||
free(ctx);
|
||||
}
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
// Free the expanded file path if it was allocated
|
||||
if (expandedFilePath)
|
||||
free(expandedFilePath);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -229,20 +206,12 @@ DWORD request_fs_file_channel_open(Remote *remote, Packet *packet)
|
||||
DWORD request_fs_separator(Remote *remote, Packet *packet)
|
||||
{
|
||||
Packet *response = packet_create_response(packet);
|
||||
#ifdef _WIN32
|
||||
LPCSTR separator = "\\";
|
||||
#else
|
||||
LPCSTR separator = "/";
|
||||
#endif
|
||||
|
||||
packet_add_tlv_string(response, TLV_TYPE_STRING, separator);
|
||||
packet_add_tlv_string(response, TLV_TYPE_STRING, FS_SEPARATOR);
|
||||
|
||||
// Set the result and transmit the response
|
||||
packet_add_tlv_uint(response, TLV_TYPE_RESULT, ERROR_SUCCESS);
|
||||
|
||||
packet_transmit(remote, response, NULL);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
return packet_transmit(remote, response, NULL);
|
||||
}
|
||||
|
||||
|
||||
@ -250,73 +219,62 @@ DWORD request_fs_separator(Remote *remote, Packet *packet)
|
||||
* Gets information about the file path that is supplied and returns it to the
|
||||
* requestor
|
||||
*
|
||||
* TLVs:
|
||||
*
|
||||
* req: TLV_TYPE_FILE_PATH - The file path that is to be stat'd
|
||||
*/
|
||||
DWORD request_fs_stat(Remote *remote, Packet *packet)
|
||||
{
|
||||
Packet *response = packet_create_response(packet);
|
||||
struct meterp_stat buf;
|
||||
LPCSTR filePath;
|
||||
LPSTR expanded = NULL;
|
||||
char *filePath;
|
||||
char *expanded = NULL;
|
||||
DWORD result = ERROR_SUCCESS;
|
||||
|
||||
filePath = packet_get_tlv_value_string(packet, TLV_TYPE_FILE_PATH);
|
||||
|
||||
// Validate parameters
|
||||
if (!filePath)
|
||||
if (!filePath) {
|
||||
result = ERROR_INVALID_PARAMETER;
|
||||
else if (!(expanded = fs_expand_path(filePath)))
|
||||
result = ERROR_NOT_ENOUGH_MEMORY;
|
||||
else
|
||||
{
|
||||
result = fs_stat(expanded, &buf);
|
||||
if (0 == result)
|
||||
packet_add_tlv_raw(response, TLV_TYPE_STAT_BUF, &buf,
|
||||
sizeof(buf));
|
||||
goto out;
|
||||
}
|
||||
|
||||
// Set the result and transmit the response
|
||||
expanded = fs_expand_path(filePath);
|
||||
if (expanded == NULL) {
|
||||
result = ERROR_NOT_ENOUGH_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
result = fs_stat(expanded, &buf);
|
||||
if (0 == result) {
|
||||
packet_add_tlv_raw(response, TLV_TYPE_STAT_BUF, &buf, sizeof(buf));
|
||||
}
|
||||
|
||||
free(expanded);
|
||||
|
||||
out:
|
||||
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
|
||||
|
||||
packet_transmit(remote, response, NULL);
|
||||
|
||||
if (expanded)
|
||||
free(expanded);
|
||||
|
||||
return result;
|
||||
return packet_transmit(remote, response, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Removes the supplied file from disk
|
||||
*
|
||||
* TLVs:
|
||||
*
|
||||
* req: TLV_TYPE_FILE_PATH - The file that is to be removed.
|
||||
*/
|
||||
DWORD request_fs_delete_file(Remote *remote, Packet *packet)
|
||||
{
|
||||
Packet *response = packet_create_response(packet);
|
||||
LPCSTR path;
|
||||
char *path;
|
||||
DWORD result = ERROR_SUCCESS;
|
||||
|
||||
path = packet_get_tlv_value_string(packet, TLV_TYPE_FILE_PATH);
|
||||
|
||||
if (!path)
|
||||
if (!path) {
|
||||
result = ERROR_INVALID_PARAMETER;
|
||||
#ifdef _WIN32
|
||||
else if (!DeleteFile(path))
|
||||
#else
|
||||
else if (unlink(path))
|
||||
#endif
|
||||
result = GetLastError();
|
||||
} else {
|
||||
result = fs_delete_file(path);
|
||||
}
|
||||
|
||||
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
|
||||
|
||||
packet_transmit(remote, response, NULL);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
return packet_transmit(remote, response, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -328,164 +286,107 @@ DWORD request_fs_file_expand_path(Remote *remote, Packet *packet)
|
||||
{
|
||||
Packet *response = packet_create_response(packet);
|
||||
DWORD result = ERROR_SUCCESS;
|
||||
LPSTR expanded = NULL;
|
||||
LPSTR regular;
|
||||
char *expanded = NULL;
|
||||
char *regular;
|
||||
|
||||
regular = packet_get_tlv_value_string(packet, TLV_TYPE_FILE_PATH);
|
||||
if (regular == NULL) {
|
||||
result = ERROR_INVALID_PARAMETER;
|
||||
goto out;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
// No regular path?
|
||||
if (!regular)
|
||||
{
|
||||
result = ERROR_INVALID_PARAMETER;
|
||||
break;
|
||||
}
|
||||
// Allocate storage for the expanded path
|
||||
expanded = fs_expand_path(regular);
|
||||
if (expanded == NULL) {
|
||||
result = ERROR_NOT_ENOUGH_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
// Allocate storage for the expanded path
|
||||
if (!(expanded = fs_expand_path(regular)))
|
||||
{
|
||||
result = ERROR_NOT_ENOUGH_MEMORY;
|
||||
break;
|
||||
}
|
||||
|
||||
packet_add_tlv_string(response, TLV_TYPE_FILE_PATH, expanded);
|
||||
|
||||
} while (0);
|
||||
|
||||
// Transmit the response to the mofo
|
||||
packet_transmit_response(result, remote, response);
|
||||
|
||||
if (expanded)
|
||||
free(expanded);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
packet_add_tlv_string(response, TLV_TYPE_FILE_PATH, expanded);
|
||||
free(expanded);
|
||||
out:
|
||||
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
|
||||
return packet_transmit(remote, response, NULL);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Returns the MD5 hash for a specified file path
|
||||
*
|
||||
* TLVs:
|
||||
*
|
||||
* req: TLV_TYPE_FILE_PATH - The file path that is to be stat'd
|
||||
*/
|
||||
DWORD request_fs_md5(Remote *remote, Packet *packet)
|
||||
{
|
||||
Packet *response = packet_create_response(packet);
|
||||
LPCSTR filePath;
|
||||
LPSTR expanded = NULL;
|
||||
char *filePath;
|
||||
DWORD result = ERROR_SUCCESS;
|
||||
MD5_CTX context;
|
||||
|
||||
FILE *fd;
|
||||
size_t ret;
|
||||
unsigned char buff[16384];
|
||||
unsigned char hash[128];
|
||||
unsigned char hash[MD5_DIGEST_LENGTH + 1] = {0};
|
||||
|
||||
filePath = packet_get_tlv_value_string(packet, TLV_TYPE_FILE_PATH);
|
||||
|
||||
// Validate parameters
|
||||
if (!filePath)
|
||||
result = ERROR_INVALID_PARAMETER;
|
||||
else if (!(expanded = fs_expand_path(filePath)))
|
||||
result = ERROR_NOT_ENOUGH_MEMORY;
|
||||
else
|
||||
{
|
||||
do {
|
||||
MD5_Init(&context);
|
||||
fd = fopen(expanded, "rb");
|
||||
if (! fd) {
|
||||
result = GetLastError();
|
||||
break;
|
||||
}
|
||||
result = fs_fopen(filePath, "rb", &fd);
|
||||
if (result == ERROR_SUCCESS) {
|
||||
|
||||
while((ret = fread(buff, 1, sizeof(buff), fd)) > 0 ) {
|
||||
MD5_Update(&context, buff, ret);
|
||||
}
|
||||
MD5_Init(&context);
|
||||
|
||||
fclose(fd);
|
||||
MD5_Final(hash, &context);
|
||||
while ((ret = fread(buff, 1, sizeof(buff), fd)) > 0 ) {
|
||||
MD5_Update(&context, buff, ret);
|
||||
}
|
||||
|
||||
// One byte extra for the NULL
|
||||
packet_add_tlv_raw(response, TLV_TYPE_FILE_NAME, hash, 17);
|
||||
} while(0);
|
||||
MD5_Final(hash, &context);
|
||||
|
||||
packet_add_tlv_raw(response, TLV_TYPE_FILE_NAME, hash, sizeof(hash));
|
||||
|
||||
fclose(fd);
|
||||
}
|
||||
|
||||
// Set the result and transmit the response
|
||||
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
|
||||
|
||||
packet_transmit(remote, response, NULL);
|
||||
|
||||
if (expanded)
|
||||
free(expanded);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
return packet_transmit(remote, response, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Returns the SHA1 hash for a specified file path
|
||||
*
|
||||
* TLVs:
|
||||
*
|
||||
* req: TLV_TYPE_FILE_PATH - The file path that is to be stat'd
|
||||
*/
|
||||
DWORD request_fs_sha1(Remote *remote, Packet *packet)
|
||||
{
|
||||
Packet *response = packet_create_response(packet);
|
||||
LPCSTR filePath;
|
||||
LPSTR expanded = NULL;
|
||||
char *filePath;
|
||||
DWORD result = ERROR_SUCCESS;
|
||||
SHA_CTX context;
|
||||
|
||||
FILE *fd;
|
||||
size_t ret;
|
||||
unsigned char buff[16384];
|
||||
unsigned char hash[128];
|
||||
unsigned char hash[SHA_DIGEST_LENGTH + 1] = {0};
|
||||
|
||||
filePath = packet_get_tlv_value_string(packet, TLV_TYPE_FILE_PATH);
|
||||
|
||||
// Validate parameters
|
||||
if (!filePath)
|
||||
result = ERROR_INVALID_PARAMETER;
|
||||
else if (!(expanded = fs_expand_path(filePath)))
|
||||
result = ERROR_NOT_ENOUGH_MEMORY;
|
||||
else
|
||||
{
|
||||
do {
|
||||
SHA1_Init(&context);
|
||||
fd = fopen(expanded, "rb");
|
||||
if (! fd) {
|
||||
result = GetLastError();
|
||||
break;
|
||||
}
|
||||
result = fs_fopen(filePath, "rb", &fd);
|
||||
if (result == ERROR_SUCCESS) {
|
||||
SHA1_Init(&context);
|
||||
|
||||
while((ret = fread(buff, 1, sizeof(buff), fd)) > 0 ) {
|
||||
SHA1_Update(&context, buff, ret);
|
||||
}
|
||||
while ((ret = fread(buff, 1, sizeof(buff), fd)) > 0 ) {
|
||||
SHA1_Update(&context, buff, ret);
|
||||
}
|
||||
|
||||
fclose(fd);
|
||||
SHA1_Final(hash, &context);
|
||||
fclose(fd);
|
||||
SHA1_Final(hash, &context);
|
||||
|
||||
// One byte extra for the NULL
|
||||
packet_add_tlv_raw(response, TLV_TYPE_FILE_NAME, hash, 21);
|
||||
} while(0);
|
||||
packet_add_tlv_raw(response, TLV_TYPE_FILE_NAME, hash, sizeof(hash));
|
||||
}
|
||||
|
||||
// Set the result and transmit the response
|
||||
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
|
||||
|
||||
packet_transmit(remote, response, NULL);
|
||||
|
||||
if (expanded)
|
||||
free(expanded);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
return packet_transmit(remote, response, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Copies source file path to destination
|
||||
*
|
||||
@ -495,25 +396,19 @@ DWORD request_fs_file_move(Remote *remote, Packet *packet)
|
||||
{
|
||||
Packet *response = packet_create_response(packet);
|
||||
DWORD result = ERROR_SUCCESS;
|
||||
LPCSTR oldpath;
|
||||
LPCSTR newpath;
|
||||
char *oldpath;
|
||||
char *newpath;
|
||||
|
||||
oldpath = packet_get_tlv_value_string(packet, TLV_TYPE_FILE_NAME);
|
||||
newpath = packet_get_tlv_value_string(packet, TLV_TYPE_FILE_PATH);
|
||||
|
||||
if (!oldpath)
|
||||
if (!oldpath) {
|
||||
result = ERROR_INVALID_PARAMETER;
|
||||
#ifdef _WIN32
|
||||
else if (!MoveFile(oldpath,newpath))
|
||||
#else
|
||||
else if (rename(oldpath,newpath))
|
||||
#endif
|
||||
result = GetLastError();
|
||||
} else {
|
||||
result = fs_move(oldpath, newpath);
|
||||
}
|
||||
|
||||
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
|
||||
|
||||
packet_transmit(remote, response, NULL);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
return packet_transmit(remote, response, NULL);
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
#ifndef _METERPRETER_SOURCE_EXTENSION_STDAPI_STDAPI_SERVER_FS_FS_H
|
||||
#define _METERPRETER_SOURCE_EXTENSION_STDAPI_STDAPI_SERVER_FS_FS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
LPSTR fs_expand_path(LPCSTR regular);
|
||||
|
||||
/*
|
||||
@ -25,33 +27,4 @@ DWORD request_fs_file_move(Remote *remote, Packet *packet);
|
||||
*/
|
||||
DWORD request_fs_file_channel_open(Remote *remote, Packet *packet);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Stat structures on Windows and various Unixes are all slightly different.
|
||||
* Use this as a means of standardization so the client has some hope of
|
||||
* understanding what the stat'd file really is.
|
||||
*/
|
||||
struct meterp_stat {
|
||||
unsigned int st_dev;
|
||||
unsigned short st_ino;
|
||||
unsigned short st_mode;
|
||||
unsigned short st_nlink;
|
||||
unsigned short st_uid;
|
||||
unsigned short st_gid;
|
||||
unsigned short pad;
|
||||
unsigned int st_rdev;
|
||||
unsigned int st_size;
|
||||
/*
|
||||
* These are always 64-bits on Windows and usually 32-bits on Linux. Force
|
||||
* them to be the same size everywhere.
|
||||
*/
|
||||
unsigned long long st_atime;
|
||||
unsigned long long st_mtime;
|
||||
unsigned long long st_ctime;
|
||||
};
|
||||
|
||||
int fs_stat(LPCSTR filename, struct meterp_stat *buf);
|
||||
|
||||
|
||||
#endif
|
||||
|
68
c/meterpreter/source/extensions/stdapi/server/fs/fs_local.h
Normal file
68
c/meterpreter/source/extensions/stdapi/server/fs/fs_local.h
Normal file
@ -0,0 +1,68 @@
|
||||
#ifndef _FS_LOCAL_H
|
||||
#define _FS_LOCAL_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#define FS_SEPARATOR "\\"
|
||||
#define FS_MAX_PATH 32768
|
||||
#else
|
||||
#define FS_SEPARATOR "/"
|
||||
#define FS_MAX_PATH PATH_MAX
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Stat structures on Windows and various Unixes are all slightly different.
|
||||
* Use this as a means of standardization so the client has some hope of
|
||||
* understanding what the stat'd file really is.
|
||||
*/
|
||||
struct meterp_stat {
|
||||
uint32_t st_dev;
|
||||
uint16_t st_ino;
|
||||
uint16_t st_mode;
|
||||
uint16_t st_nlink;
|
||||
uint16_t st_uid;
|
||||
uint16_t st_gid;
|
||||
uint16_t pad;
|
||||
uint32_t st_rdev;
|
||||
uint32_t st_size;
|
||||
/*
|
||||
* These are always 64-bits on Windows and usually 32-bits on Linux. Force
|
||||
* them to be the same size everywhere.
|
||||
*/
|
||||
uint64_t st_atime;
|
||||
uint64_t st_mtime;
|
||||
uint64_t st_ctime;
|
||||
};
|
||||
|
||||
typedef void (*fs_ls_cb_t)(void *arg, char *name, char *short_name, char *path);
|
||||
|
||||
int fs_chdir(const char *directory);
|
||||
|
||||
int fs_delete_dir(const char *directory);
|
||||
|
||||
int fs_delete_file(const char *path);
|
||||
|
||||
/*
|
||||
* Returns an expanded file path that must be freed
|
||||
*/
|
||||
char * fs_expand_path(const char *regular);
|
||||
|
||||
int fs_fopen(const char *path, const char *mode, FILE **f);
|
||||
|
||||
int fs_ls(const char *directory, fs_ls_cb_t cb, void *arg);
|
||||
|
||||
int fs_getwd(char **directory);
|
||||
|
||||
int fs_mkdir(const char *directory);
|
||||
|
||||
int fs_move(const char *oldpath, const char *newpath);
|
||||
|
||||
/*
|
||||
* Fills the platform-independent meterp_stat buf with data from the
|
||||
* platform-dependent stat()
|
||||
*/
|
||||
int fs_stat(char *filename, struct meterp_stat *buf);
|
||||
|
||||
#endif
|
126
c/meterpreter/source/extensions/stdapi/server/fs/fs_posix.c
Normal file
126
c/meterpreter/source/extensions/stdapi/server/fs/fs_posix.c
Normal file
@ -0,0 +1,126 @@
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "precomp.h"
|
||||
#include "fs_local.h"
|
||||
|
||||
int fs_ls(const char *directory, fs_ls_cb_t cb, void *arg)
|
||||
{
|
||||
struct meterp_stat s;
|
||||
struct dirent *data;
|
||||
char path[FS_MAX_PATH];
|
||||
|
||||
DIR *ctx = opendir(directory);
|
||||
if (ctx == NULL) {
|
||||
return errno;
|
||||
}
|
||||
|
||||
while ((data = readdir(ctx))) {
|
||||
|
||||
snprintf(path, sizeof(path), "%s/%s", directory, data->d_name);
|
||||
|
||||
cb(arg, data->d_name, NULL, path);
|
||||
}
|
||||
|
||||
closedir(ctx);
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
int fs_chdir(const char *directory)
|
||||
{
|
||||
if (chdir(directory) == -1) {
|
||||
return errno;
|
||||
}
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
int fs_delete_file(const char *path)
|
||||
{
|
||||
if (unlink(path) == -1) {
|
||||
return errno;
|
||||
}
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
int fs_delete_dir(const char *directory)
|
||||
{
|
||||
if (rmdir(directory) == -1) {
|
||||
return errno;
|
||||
}
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
char * fs_expand_path(const char *regular)
|
||||
{
|
||||
return strdup(regular);
|
||||
}
|
||||
|
||||
int fs_getwd(char **directory)
|
||||
{
|
||||
char dir[FS_MAX_PATH];
|
||||
if (getcwd(dir, sizeof(dir)) == NULL) {
|
||||
return errno;
|
||||
}
|
||||
*directory = strdup(dir);
|
||||
return *directory == NULL ? ERROR_NOT_ENOUGH_MEMORY : ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
int fs_mkdir(const char *directory)
|
||||
{
|
||||
if (mkdir(directory, 0777) == -1) {
|
||||
return errno;
|
||||
}
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
int fs_fopen(const char *path, const char *mode, FILE **f)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (path == NULL || f == NULL) {
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
*f = fopen(path, mode);
|
||||
if (*f == NULL) {
|
||||
rc = errno;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int fs_move(const char *oldpath, const char *newpath)
|
||||
{
|
||||
if (rename(oldpath, newpath) == -1) {
|
||||
return errno;
|
||||
}
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
int fs_stat(char *filename, struct meterp_stat *buf)
|
||||
{
|
||||
struct stat sbuf;
|
||||
|
||||
if (stat(filename, &sbuf) == -1) {
|
||||
return errno;
|
||||
}
|
||||
|
||||
buf->st_dev = sbuf.st_dev;
|
||||
buf->st_ino = sbuf.st_ino;
|
||||
buf->st_mode = sbuf.st_mode;
|
||||
buf->st_nlink = sbuf.st_nlink;
|
||||
buf->st_uid = sbuf.st_uid;
|
||||
buf->st_gid = sbuf.st_gid;
|
||||
buf->st_rdev = sbuf.st_rdev;
|
||||
buf->st_size = sbuf.st_size;
|
||||
buf->st_atime = sbuf.st_atime;
|
||||
buf->st_mtime = sbuf.st_mtime;
|
||||
buf->st_ctime = sbuf.st_ctime;
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
@ -1,75 +0,0 @@
|
||||
#include "precomp.h"
|
||||
#include "fs.h"
|
||||
#include <sys/stat.h>
|
||||
|
||||
/*
|
||||
* Returns an expanded file path that must be freed
|
||||
*/
|
||||
LPSTR fs_expand_path(LPCSTR regular)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
DWORD expandedFilePathSize = 32768;
|
||||
LPSTR expandedFilePath = NULL;
|
||||
|
||||
do
|
||||
{
|
||||
// Expand the file path
|
||||
if (!(expandedFilePath = (LPSTR)malloc(expandedFilePathSize)))
|
||||
break;
|
||||
|
||||
// Expand the file path being accessed
|
||||
if (!ExpandEnvironmentStrings(regular, expandedFilePath,
|
||||
expandedFilePathSize - 1))
|
||||
{
|
||||
free(expandedFilePath);
|
||||
|
||||
expandedFilePath = 0;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
expandedFilePath[expandedFilePathSize - 1] = 0;
|
||||
|
||||
} while (0);
|
||||
|
||||
return expandedFilePath;
|
||||
#else /* Hack to make it work with existing code under *nix */
|
||||
char *expandedFilePath;
|
||||
DWORD expandedFilePathSize = strlen(regular)+1;
|
||||
expandedFilePath = malloc(expandedFilePathSize);
|
||||
strncpy(expandedFilePath, regular, expandedFilePathSize);
|
||||
expandedFilePath[expandedFilePathSize - 1] = '\0';
|
||||
return expandedFilePath;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Fills the platform-independent meterp_stat buf with data from the platform-dependent stat()
|
||||
*/
|
||||
int fs_stat(LPCSTR filename, struct meterp_stat *buf) {
|
||||
struct stat sbuf;
|
||||
int ret;
|
||||
|
||||
ret = stat(filename, &sbuf);
|
||||
|
||||
if (ret == 0) {
|
||||
buf->st_dev = sbuf.st_dev;
|
||||
buf->st_ino = sbuf.st_ino;
|
||||
buf->st_mode = sbuf.st_mode;
|
||||
buf->st_nlink = sbuf.st_nlink;
|
||||
buf->st_uid = sbuf.st_uid;
|
||||
buf->st_gid = sbuf.st_gid;
|
||||
buf->st_rdev = sbuf.st_rdev;
|
||||
buf->st_size = sbuf.st_size;
|
||||
buf->st_atime = (unsigned long long)sbuf.st_atime;
|
||||
buf->st_mtime = (unsigned long long)sbuf.st_mtime;
|
||||
buf->st_ctime = (unsigned long long)sbuf.st_ctime;
|
||||
return 0;
|
||||
} else {
|
||||
#ifdef _WIN32
|
||||
return GetLastError();
|
||||
#else
|
||||
return errno;
|
||||
#endif
|
||||
}
|
||||
}
|
339
c/meterpreter/source/extensions/stdapi/server/fs/fs_win.c
Normal file
339
c/meterpreter/source/extensions/stdapi/server/fs/fs_win.c
Normal file
@ -0,0 +1,339 @@
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "fs_local.h"
|
||||
#include "precomp.h"
|
||||
|
||||
static wchar_t *utf8_to_wchar(const char *in)
|
||||
{
|
||||
wchar_t *out;
|
||||
int len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, in, -1, NULL, 0);
|
||||
if (len <= 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
out = calloc(len, sizeof(wchar_t));
|
||||
if (out == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (MultiByteToWideChar(CP_UTF8, 0, in, -1, out, len) == 0) {
|
||||
free(out);
|
||||
out = NULL;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
static char *wchar_to_utf8(const wchar_t *in)
|
||||
{
|
||||
char *out;
|
||||
int len = WideCharToMultiByte(CP_UTF8, 0, in, -1, NULL, 0, NULL, NULL);
|
||||
if (len <= 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
out = calloc(len, sizeof(char));
|
||||
if (out == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (WideCharToMultiByte(CP_UTF8, 0, in, -1, out, len, NULL, FALSE) == 0) {
|
||||
free(out);
|
||||
out = NULL;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
char * fs_expand_path(const char *regular)
|
||||
{
|
||||
wchar_t expanded_path[FS_MAX_PATH];
|
||||
wchar_t *regular_w;
|
||||
|
||||
regular_w = utf8_to_wchar(regular);
|
||||
if (regular_w == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (ExpandEnvironmentStringsW(regular_w, expanded_path, FS_MAX_PATH) == 0) {
|
||||
free(regular_w);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
free(regular_w);
|
||||
|
||||
return wchar_to_utf8(expanded_path);
|
||||
}
|
||||
|
||||
int fs_ls(const char *directory, fs_ls_cb_t cb, void *arg)
|
||||
{
|
||||
DWORD result = 0;
|
||||
LPSTR expanded = NULL;
|
||||
LPSTR baseDirectory = NULL;
|
||||
char tempDirectory[FS_MAX_PATH];
|
||||
|
||||
_snprintf(tempDirectory, sizeof(tempDirectory), "%s", directory);
|
||||
|
||||
/*
|
||||
* If there is not wildcard mask on the directory, create a version of the
|
||||
* directory with a mask appended
|
||||
*/
|
||||
if (strrchr(directory, '*') == NULL) {
|
||||
_snprintf(tempDirectory, sizeof(tempDirectory), "%s\\*",
|
||||
directory);
|
||||
|
||||
baseDirectory = _strdup(directory);
|
||||
if (baseDirectory == NULL) {
|
||||
result = ERROR_NOT_ENOUGH_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
} else {
|
||||
/*
|
||||
* Otherwise, if it does have an asterisk, we need to scan back
|
||||
* and find the base directory. If there is no slash, it means
|
||||
* we're listing the cwd.
|
||||
*/
|
||||
PCHAR slash = strrchr(directory, '\\');
|
||||
if (slash) {
|
||||
*slash = 0;
|
||||
baseDirectory = _strdup(directory);
|
||||
if (baseDirectory == NULL) {
|
||||
result = ERROR_NOT_ENOUGH_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
*slash = '\\';
|
||||
}
|
||||
}
|
||||
|
||||
expanded = fs_expand_path(tempDirectory);
|
||||
if (expanded == NULL) {
|
||||
result = ERROR_NOT_ENOUGH_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
WIN32_FIND_DATAW data;
|
||||
wchar_t *path_w = utf8_to_wchar(expanded);
|
||||
if (path_w == NULL) {
|
||||
result = GetLastError();
|
||||
goto out;
|
||||
}
|
||||
|
||||
HANDLE ctx = FindFirstFileW(path_w, &data);
|
||||
if (ctx == NULL) {
|
||||
result = GetLastError();
|
||||
goto out;
|
||||
}
|
||||
|
||||
do {
|
||||
if (ctx == INVALID_HANDLE_VALUE) {
|
||||
result = GetLastError();
|
||||
break;
|
||||
}
|
||||
|
||||
char *filename = wchar_to_utf8(data.cFileName);
|
||||
char *short_filename = wchar_to_utf8(data.cAlternateFileName);
|
||||
char path[FS_MAX_PATH];
|
||||
|
||||
if (baseDirectory) {
|
||||
_snprintf(path, sizeof(path), "%s\\%s", baseDirectory, filename);
|
||||
} else {
|
||||
_snprintf(path, sizeof(path), "%s", filename);
|
||||
}
|
||||
|
||||
cb(arg, filename, short_filename, path);
|
||||
|
||||
free(filename);
|
||||
free(short_filename);
|
||||
|
||||
} while (FindNextFileW(ctx, &data));
|
||||
|
||||
/*
|
||||
* Clean up resources
|
||||
*/
|
||||
FindClose(ctx);
|
||||
free(expanded);
|
||||
out:
|
||||
free(baseDirectory);
|
||||
free(path_w);
|
||||
return result;
|
||||
}
|
||||
|
||||
int fs_chdir(const char *directory)
|
||||
{
|
||||
int rc = ERROR_SUCCESS;
|
||||
wchar_t *dir_w = utf8_to_wchar(directory);
|
||||
|
||||
if (dir_w == NULL) {
|
||||
rc = GetLastError();
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (SetCurrentDirectoryW(dir_w) == 0) {
|
||||
rc = GetLastError();
|
||||
}
|
||||
|
||||
out:
|
||||
free(dir_w);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int fs_delete_dir(const char *directory)
|
||||
{
|
||||
int rc = ERROR_SUCCESS;
|
||||
wchar_t *dir_w = utf8_to_wchar(directory);
|
||||
|
||||
if (dir_w == NULL) {
|
||||
rc = GetLastError();
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (RemoveDirectoryW(dir_w) == 0) {
|
||||
rc = GetLastError();
|
||||
}
|
||||
|
||||
out:
|
||||
free(dir_w);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int fs_delete_file(const char *path)
|
||||
{
|
||||
int rc = ERROR_SUCCESS;
|
||||
wchar_t *path_w = utf8_to_wchar(path);
|
||||
|
||||
if (path_w == NULL) {
|
||||
rc = GetLastError();
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (DeleteFileW(path_w) == 0) {
|
||||
rc = GetLastError();
|
||||
}
|
||||
|
||||
out:
|
||||
free(path_w);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int fs_getwd(char **dir)
|
||||
{
|
||||
int rc = ERROR_SUCCESS;
|
||||
wchar_t dir_w[FS_MAX_PATH];
|
||||
|
||||
if (GetCurrentDirectoryW(FS_MAX_PATH, dir_w) == 0) {
|
||||
rc = GetLastError();
|
||||
goto out;
|
||||
}
|
||||
|
||||
*dir = wchar_to_utf8(dir_w);
|
||||
if (*dir == NULL) {
|
||||
rc = GetLastError();
|
||||
}
|
||||
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int fs_move(const char *oldpath, const char *newpath)
|
||||
{
|
||||
int rc = ERROR_SUCCESS;
|
||||
wchar_t *old_w = utf8_to_wchar(oldpath);
|
||||
wchar_t *new_w = utf8_to_wchar(newpath);
|
||||
|
||||
if ((old_w == NULL) || (new_w == NULL)) {
|
||||
rc = GetLastError();
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (MoveFileW(old_w, new_w) == 0) {
|
||||
rc = GetLastError();
|
||||
}
|
||||
|
||||
out:
|
||||
free(old_w);
|
||||
free(new_w);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int fs_mkdir(const char *directory)
|
||||
{
|
||||
int rc = ERROR_SUCCESS;
|
||||
wchar_t *dir_w = utf8_to_wchar(directory);
|
||||
|
||||
if (dir_w == NULL) {
|
||||
rc = GetLastError();
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (CreateDirectoryW(dir_w, NULL) == 0) {
|
||||
rc = GetLastError();
|
||||
}
|
||||
|
||||
out:
|
||||
free(dir_w);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int fs_fopen(const char *path, const char *mode, FILE **f)
|
||||
{
|
||||
char *expanded = NULL;
|
||||
int rc = ERROR_SUCCESS;
|
||||
|
||||
if (path == NULL || f == NULL) {
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if ((expanded = fs_expand_path(path)) == NULL) {
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
|
||||
wchar_t *path_w = utf8_to_wchar(expanded);
|
||||
wchar_t *mode_w = utf8_to_wchar(mode);
|
||||
|
||||
if ((path_w == NULL) || (mode_w == NULL)) {
|
||||
rc = ERROR_NOT_ENOUGH_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
*f = _wfopen(path_w, mode_w);
|
||||
if (*f == NULL) {
|
||||
rc = GetLastError();
|
||||
}
|
||||
|
||||
out:
|
||||
free(expanded);
|
||||
free(path_w);
|
||||
free(mode_w);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int fs_stat(char *filename, struct meterp_stat *buf)
|
||||
{
|
||||
struct _stat64i32 sbuf;
|
||||
|
||||
wchar_t *filename_w = utf8_to_wchar(filename);
|
||||
if (filename_w == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (_wstat(filename_w, &sbuf) == -1) {
|
||||
return GetLastError();
|
||||
}
|
||||
|
||||
free(filename_w);
|
||||
|
||||
buf->st_dev = sbuf.st_dev;
|
||||
buf->st_ino = sbuf.st_ino;
|
||||
buf->st_mode = sbuf.st_mode;
|
||||
buf->st_nlink = sbuf.st_nlink;
|
||||
buf->st_uid = sbuf.st_uid;
|
||||
buf->st_gid = sbuf.st_gid;
|
||||
buf->st_rdev = sbuf.st_rdev;
|
||||
buf->st_size = sbuf.st_size;
|
||||
buf->st_atime = sbuf.st_atime;
|
||||
buf->st_mtime = sbuf.st_mtime;
|
||||
buf->st_ctime = sbuf.st_ctime;
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
@ -216,8 +216,16 @@ DWORD DeinitServerExtension(Remote *remote)
|
||||
* @param bufferSize Size of the \c buffer parameter.
|
||||
* @return Indication of success or failure.
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
DWORD __declspec(dllexport) GetExtensionName(char* buffer, int bufferSize)
|
||||
#else
|
||||
DWORD GetExtensionName(char* buffer, int bufferSize)
|
||||
#endif
|
||||
{
|
||||
#ifdef _WIN32
|
||||
strncpy_s(buffer, bufferSize, "stdapi", bufferSize - 1);
|
||||
#else
|
||||
strncpy(buffer, "stdapi", bufferSize - 1);
|
||||
#endif
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
@ -23,6 +23,7 @@
|
||||
#define TLV_TYPE_FILE_PATH MAKE_CUSTOM_TLV( TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_STDAPI, 1202 )
|
||||
#define TLV_TYPE_FILE_MODE MAKE_CUSTOM_TLV( TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_STDAPI, 1203 )
|
||||
#define TLV_TYPE_FILE_SIZE MAKE_CUSTOM_TLV( TLV_META_TYPE_UINT, TLV_TYPE_EXTENSION_STDAPI, 1204 )
|
||||
#define TLV_TYPE_FILE_SHORT_NAME MAKE_CUSTOM_TLV( TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_STDAPI, 1205 )
|
||||
|
||||
#define TLV_TYPE_STAT_BUF MAKE_CUSTOM_TLV( TLV_META_TYPE_COMPLEX, TLV_TYPE_EXTENSION_STDAPI, 1220 )
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include "metsrv.h"
|
||||
|
||||
extern Command *extensionCommands;
|
||||
extern PLIST gExtensionList;
|
||||
|
||||
DWORD request_core_loadlib(Remote *remote, Packet *packet)
|
||||
{
|
||||
@ -61,15 +62,37 @@ DWORD request_core_loadlib(Remote *remote, Packet *packet)
|
||||
// call its Init routine
|
||||
if (flags & LOAD_LIBRARY_FLAG_EXTENSION)
|
||||
{
|
||||
DWORD(*init)(Remote *remote);
|
||||
PEXTENSION pExtension = (PEXTENSION)malloc(sizeof(EXTENSION));
|
||||
if (!pExtension)
|
||||
{
|
||||
res = ERROR_NOT_ENOUGH_MEMORY;
|
||||
break;
|
||||
}
|
||||
//DWORD(*init)(Remote *remote);
|
||||
|
||||
pExtension->init = dlsym(library, "InitServerExtension");
|
||||
|
||||
init = dlsym(library, "InitServerExtension");
|
||||
// Call the init routine in the library
|
||||
if (init)
|
||||
if (pExtension->init)
|
||||
{
|
||||
dprintf("calling InitServerExtension");
|
||||
res = init(remote);
|
||||
res = pExtension->init(remote);
|
||||
pExtension->getname = dlsym(library, "GetExtensionName");
|
||||
|
||||
|
||||
pExtension->deinit = dlsym(library, "DeinitServerExtension");
|
||||
|
||||
if (pExtension->getname)
|
||||
{
|
||||
pExtension->getname(pExtension->name, sizeof(pExtension->name));
|
||||
}
|
||||
list_push(gExtensionList, pExtension);
|
||||
}
|
||||
else
|
||||
{
|
||||
free(pExtension);
|
||||
}
|
||||
|
||||
if (response)
|
||||
{
|
||||
for (command = extensionCommands; command != first; command = command->next)
|
||||
|
@ -7,6 +7,8 @@ extern HINSTANCE hAppInstance;
|
||||
|
||||
PLIST gExtensionList = NULL;
|
||||
|
||||
DWORD request_core_enumextcmd(Remote* pRemote, Packet* pPacket);
|
||||
|
||||
// Dispatch table
|
||||
Command customCommands[] =
|
||||
{
|
||||
@ -15,6 +17,56 @@ Command customCommands[] =
|
||||
COMMAND_TERMINATOR
|
||||
};
|
||||
|
||||
typedef struct _EnumExtensions
|
||||
{
|
||||
Packet* pResponse;
|
||||
char* lpExtensionName;
|
||||
} EnumExtensions, * PEnumExtensions;
|
||||
|
||||
BOOL ext_cmd_callback(LPVOID pState, LPVOID pData)
|
||||
{
|
||||
PEnumExtensions pEnum = (PEnumExtensions)pState;
|
||||
Command* command = NULL;
|
||||
|
||||
if (pEnum != NULL && pEnum->pResponse != NULL && pData != NULL)
|
||||
{
|
||||
PEXTENSION pExt = (PEXTENSION)pData;
|
||||
if (pExt->name[0] != '\0' && pEnum->lpExtensionName != NULL && strcmp(pExt->name, pEnum->lpExtensionName) == 0)
|
||||
{
|
||||
dprintf("[LISTEXT] Found extension: %s", pExt->name);
|
||||
for (command = pExt->start; command != pExt->end; command = command->next)
|
||||
{
|
||||
packet_add_tlv_string(pEnum->pResponse, TLV_TYPE_STRING, command->method);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
DWORD request_core_enumextcmd(Remote* pRemote, Packet* pPacket)
|
||||
{
|
||||
BOOL bResult = FALSE;
|
||||
Packet* pResponse = packet_create_response(pPacket);
|
||||
|
||||
if (pResponse != NULL)
|
||||
{
|
||||
EnumExtensions enumExt;
|
||||
enumExt.pResponse = pResponse;
|
||||
enumExt.lpExtensionName = packet_get_tlv_value_string(pPacket, TLV_TYPE_STRING);
|
||||
|
||||
dprintf("[LISTEXTCMD] Listing extension commands for %s ...", enumExt.lpExtensionName);
|
||||
// Start by enumerating the names of the extensions
|
||||
bResult = list_enumerate(gExtensionList, ext_cmd_callback, &enumExt);
|
||||
|
||||
packet_add_tlv_uint(pResponse, TLV_TYPE_RESULT, ERROR_SUCCESS);
|
||||
packet_transmit(pRemote, pResponse, NULL);
|
||||
}
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Registers custom command handlers
|
||||
*/
|
||||
@ -38,7 +90,10 @@ VOID deregister_dispatch_routines(Remote * remote)
|
||||
break;
|
||||
}
|
||||
|
||||
extension->deinit(remote);
|
||||
if (extension->deinit)
|
||||
{
|
||||
extension->deinit(remote);
|
||||
}
|
||||
|
||||
free(extension);
|
||||
}
|
||||
|
@ -8,54 +8,6 @@ extern PLIST gExtensionList;
|
||||
// see common/base.c
|
||||
extern Command *extensionCommands;
|
||||
|
||||
typedef struct _EnumExtensions
|
||||
{
|
||||
Packet* pResponse;
|
||||
char* lpExtensionName;
|
||||
} EnumExtensions, * PEnumExtensions;
|
||||
|
||||
BOOL ext_cmd_callback(LPVOID pState, LPVOID pData)
|
||||
{
|
||||
PEnumExtensions pEnum = (PEnumExtensions)pState;
|
||||
|
||||
if (pEnum != NULL && pEnum->pResponse != NULL && pData != NULL)
|
||||
{
|
||||
PEXTENSION pExt = (PEXTENSION)pData;
|
||||
if (pExt->name[0] != '\0' && pEnum->lpExtensionName != NULL && strcmp(pExt->name, pEnum->lpExtensionName) == 0)
|
||||
{
|
||||
dprintf("[LISTEXT] Found extension: %s", pExt->name);
|
||||
for (Command* command = pExt->start; command != pExt->end; command = command->next)
|
||||
{
|
||||
packet_add_tlv_string(pEnum->pResponse, TLV_TYPE_STRING, command->method);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
DWORD request_core_enumextcmd(Remote* pRemote, Packet* pPacket)
|
||||
{
|
||||
Packet* pResponse = packet_create_response(pPacket);
|
||||
|
||||
if (pResponse != NULL)
|
||||
{
|
||||
EnumExtensions enumExt;
|
||||
enumExt.pResponse = pResponse;
|
||||
enumExt.lpExtensionName = packet_get_tlv_value_string(pPacket, TLV_TYPE_STRING);
|
||||
|
||||
dprintf("[LISTEXTCMD] Listing extension commands for %s ...", enumExt.lpExtensionName);
|
||||
// Start by enumerating the names of the extensions
|
||||
BOOL bResult = list_enumerate(gExtensionList, ext_cmd_callback, &enumExt);
|
||||
|
||||
packet_add_tlv_uint(pResponse, TLV_TYPE_RESULT, ERROR_SUCCESS);
|
||||
packet_transmit(pRemote, pResponse, NULL);
|
||||
}
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
DWORD initialise_extension(HMODULE hLibrary, BOOL bLibLoadedReflectivly, Remote* pRemote, Packet* pResponse, Command* pFirstCommand)
|
||||
{
|
||||
DWORD dwResult = ERROR_OUTOFMEMORY;
|
||||
@ -129,6 +81,8 @@ DWORD initialise_extension(HMODULE hLibrary, BOOL bLibLoadedReflectivly, Remote*
|
||||
return dwResult;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* core_loadlib
|
||||
* ------------
|
||||
|
@ -9,7 +9,7 @@ CFLAGS+= -I../../source/extensions/stdapi/server
|
||||
objects = \
|
||||
server/fs/dir.o \
|
||||
server/fs/file.o \
|
||||
server/fs/fs_util.o \
|
||||
server/fs/fs_posix.o \
|
||||
server/general.o \
|
||||
server/net/config/interface.o \
|
||||
server/net/config/route.o \
|
||||
|
@ -633,7 +633,7 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformSho
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\extensions\stdapi\server\fs\dir.c" />
|
||||
<ClCompile Include="..\..\source\extensions\stdapi\server\fs\file.c" />
|
||||
<ClCompile Include="..\..\source\extensions\stdapi\server\fs\fs_util.c" />
|
||||
<ClCompile Include="..\..\source\extensions\stdapi\server\fs\fs_win.c" />
|
||||
<ClCompile Include="..\..\source\extensions\stdapi\server\fs\search.c" />
|
||||
<ClCompile Include="..\..\source\extensions\stdapi\server\net\net.c" />
|
||||
<ClCompile Include="..\..\source\extensions\stdapi\server\net\config\interface.c" />
|
||||
@ -687,6 +687,7 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformSho
|
||||
<ClInclude Include="..\..\source\extensions\stdapi\server\webcam\bmp2jpeg.h" />
|
||||
<ClInclude Include="..\..\source\extensions\stdapi\server\webcam\webcam.h" />
|
||||
<ClInclude Include="..\..\source\extensions\stdapi\server\fs\fs.h" />
|
||||
<ClInclude Include="..\..\source\extensions\stdapi\server\fs\fs_local.h" />
|
||||
<ClInclude Include="..\..\source\extensions\stdapi\server\fs\search.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@ -714,4 +715,4 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformSho
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.targets" />
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
Loading…
x
Reference in New Issue
Block a user