1
mirror of https://github.com/rapid7/metasploit-payloads synced 2025-08-09 18:12:28 +02:00
Files
OJ 7702724fd2 Remove all warnings resulting in totally clean builds
Does as it says on the tin. Various tweaks made to source and to project
files to make the builds come out with ZERO warnings.

Let's keep it clean from here!
2013-11-06 19:02:50 +10:00

520 lines
11 KiB
C

#include "precomp.h"
#include <sys/stat.h>
#include <openssl/md5.h>
#include <openssl/sha.h>
/***************************
* File Channel Operations *
***************************/
typedef struct
{
FILE *fd;
DWORD mode;
} FileContext;
/*
* Writes the supplied data to the file
*/
static DWORD file_channel_write(Channel *channel, Packet *request,
LPVOID context, LPVOID buffer, DWORD bufferSize,
LPDWORD bytesWritten)
{
FileContext *ctx = (FileContext *)context;
DWORD result= ERROR_SUCCESS;
DWORD written = 0;
// Write a chunk
if ((written = (DWORD)fwrite(buffer, 1, bufferSize, ctx->fd)) <= 0)
{
written = 0;
result = GetLastError();
}
// Set bytesWritten
if (bytesWritten)
{
*bytesWritten = written;
}
return result;
}
/*
* Closes the file
*/
static DWORD file_channel_close(Channel *channel, Packet *request,
LPVOID context)
{
FileContext *ctx = (FileContext *)context;
fclose(ctx->fd);
free(ctx);
return ERROR_SUCCESS;
}
/*
* Reads data from the file (if any)
*/
static DWORD file_channel_read(Channel *channel, Packet *request,
LPVOID context, LPVOID buffer, DWORD bufferSize,
LPDWORD bytesRead)
{
FileContext *ctx = (FileContext *)context;
DWORD result = ERROR_SUCCESS;
DWORD bytes = 0;
// Read a chunk
if ((bytes= (DWORD)fread(buffer, 1, bufferSize, ctx->fd)) <= 0)
{
bytes = 0;
result = GetLastError();
}
// Set bytesRead
if (bytesRead)
*bytesRead = bytes;
return ERROR_SUCCESS;
}
/*
* Checks to see if the file pointer is currently at the end of the file
*/
static DWORD file_channel_eof(Channel *channel, Packet *request,
LPVOID context, LPBOOL isEof)
{
FileContext *ctx = (FileContext *)context;
*isEof = feof(ctx->fd) ? TRUE : FALSE;
return ERROR_SUCCESS;
}
/*
* Changes the current file pointer position in the file
*/
static DWORD file_channel_seek(Channel *channel, Packet *request,
LPVOID context, LONG offset, DWORD whence)
{
FileContext *ctx = (FileContext *)context;
return fseek(ctx->fd, offset, whence);
}
/*
* Returns the current offset in the file to the requestor
*/
static DWORD file_channel_tell(Channel *channel, Packet *request,
LPVOID context, LPLONG offset)
{
FileContext *ctx = (FileContext *)context;
DWORD result = ERROR_SUCCESS;
LONG pos = 0;
if ((pos = ftell(ctx->fd)) < 0)
result = GetLastError();
if (offset)
*offset = pos;
return result;
}
/*
* Handles the open request for a file channel and returns a valid channel
* identifier to the requestor if the file is opened successfully
*/
DWORD request_fs_file_channel_open(Remote *remote, Packet *packet)
{
Packet *response = NULL;
PCHAR filePath, mode;
DWORD res = ERROR_SUCCESS;
DWORD flags = 0;
Channel *newChannel = NULL;
PoolChannelOps chops = { 0 };
FileContext *ctx;
LPSTR expandedFilePath = NULL;
do
{
// Allocate a response
response = packet_create_response(packet);
// 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;
}
// 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;
}
// Expand the file path
if (!(expandedFilePath = fs_expand_path(filePath)))
{
res = ERROR_NOT_ENOUGH_MEMORY;
break;
}
if (!mode)
mode = "rb";
// Invalid file?
if (!(ctx->fd = fopen(expandedFilePath, mode)))
{
res = GetLastError();
break;
}
memset(&chops, 0, sizeof(chops));
// 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);
// Transmit the packet if it's valid
packet_transmit_response(res, remote, response);
// Clean up on failure
if (res != ERROR_SUCCESS)
{
if (newChannel)
channel_destroy(newChannel, NULL);
if (ctx)
free(ctx);
}
// Free the expanded file path if it was allocated
if (expandedFilePath)
free(expandedFilePath);
return res;
}
/*
* Gets the directory separator for this system
*/
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);
// 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;
}
/*
* 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;
DWORD result = ERROR_SUCCESS;
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
{
result = fs_stat(expanded, &buf);
if (0 == result)
packet_add_tlv_raw(response, TLV_TYPE_STAT_BUF, &buf,
sizeof(buf));
}
// 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 result;
}
/*
* 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;
DWORD result = ERROR_SUCCESS;
path = packet_get_tlv_value_string(packet, TLV_TYPE_FILE_PATH);
if (!path)
result = ERROR_INVALID_PARAMETER;
#ifdef _WIN32
else if (!DeleteFile(path))
#else
else if (!unlink(path))
#endif
result = GetLastError();
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
packet_transmit(remote, response, NULL);
return ERROR_SUCCESS;
}
/*
* Expands a file path and returns the expanded path to the requestor
*
* req: TLV_TYPE_FILE_PATH - The file path to expand
*/
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;
regular = packet_get_tlv_value_string(packet, TLV_TYPE_FILE_PATH);
do
{
// No regular path?
if (!regular)
{
result = ERROR_INVALID_PARAMETER;
break;
}
// 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;
}
/*
* 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;
DWORD result = ERROR_SUCCESS;
MD5_CTX context;
FILE *fd;
size_t ret;
unsigned char buff[16384];
unsigned char hash[128];
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;
}
while((ret = fread(buff, 1, sizeof(buff), fd)) > 0 ) {
MD5_Update(&context, buff, ret);
}
fclose(fd);
MD5_Final(hash, &context);
// One byte extra for the NULL
packet_add_tlv_raw(response, TLV_TYPE_FILE_NAME, hash, 17);
} while(0);
}
// 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;
}
/*
* 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;
DWORD result = ERROR_SUCCESS;
SHA_CTX context;
FILE *fd;
size_t ret;
unsigned char buff[16384];
unsigned char hash[128];
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;
}
while((ret = fread(buff, 1, sizeof(buff), fd)) > 0 ) {
SHA1_Update(&context, buff, ret);
}
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);
}
// 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;
}
/*
* Copies source file path to destination
*
* req: TLV_TYPE_FILE_PATH - The file path to expand
*/
DWORD request_fs_file_move(Remote *remote, Packet *packet)
{
Packet *response = packet_create_response(packet);
DWORD result = ERROR_SUCCESS;
LPCSTR oldpath;
LPCSTR 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)
result = ERROR_INVALID_PARAMETER;
#ifdef _WIN32
else if (!MoveFile(oldpath,newpath))
#else
else if (!rename(oldpath,newpath))
#endif
result = GetLastError();
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
packet_transmit(remote, response, NULL);
return ERROR_SUCCESS;
}