diff --git a/c/meterpreter/source/extensions/networkpug/networkpug.c b/c/meterpreter/source/extensions/networkpug/networkpug.c index 2bdf6b16..cbea7e45 100644 --- a/c/meterpreter/source/extensions/networkpug/networkpug.c +++ b/c/meterpreter/source/extensions/networkpug/networkpug.c @@ -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; +} diff --git a/c/meterpreter/source/extensions/sniffer/sniffer.c b/c/meterpreter/source/extensions/sniffer/sniffer.c index a4430a3d..efa06096 100644 --- a/c/meterpreter/source/extensions/sniffer/sniffer.c +++ b/c/meterpreter/source/extensions/sniffer/sniffer.c @@ -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; -} \ No newline at end of file +} diff --git a/c/meterpreter/source/extensions/stdapi/server/fs/dir.c b/c/meterpreter/source/extensions/stdapi/server/fs/dir.c index a94e3b3f..cf3b1662 100644 --- a/c/meterpreter/source/extensions/stdapi/server/fs/dir.c +++ b/c/meterpreter/source/extensions/stdapi/server/fs/dir.c @@ -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); +} diff --git a/c/meterpreter/source/extensions/stdapi/server/fs/file.c b/c/meterpreter/source/extensions/stdapi/server/fs/file.c index 5b45959b..a3b7e256 100644 --- a/c/meterpreter/source/extensions/stdapi/server/fs/file.c +++ b/c/meterpreter/source/extensions/stdapi/server/fs/file.c @@ -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); } diff --git a/c/meterpreter/source/extensions/stdapi/server/fs/fs.h b/c/meterpreter/source/extensions/stdapi/server/fs/fs.h index 517fc961..3d1ccf4a 100644 --- a/c/meterpreter/source/extensions/stdapi/server/fs/fs.h +++ b/c/meterpreter/source/extensions/stdapi/server/fs/fs.h @@ -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 diff --git a/c/meterpreter/source/extensions/stdapi/server/fs/fs_local.h b/c/meterpreter/source/extensions/stdapi/server/fs/fs_local.h new file mode 100644 index 00000000..4a6b615b --- /dev/null +++ b/c/meterpreter/source/extensions/stdapi/server/fs/fs_local.h @@ -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 diff --git a/c/meterpreter/source/extensions/stdapi/server/fs/fs_posix.c b/c/meterpreter/source/extensions/stdapi/server/fs/fs_posix.c new file mode 100644 index 00000000..3fc9054a --- /dev/null +++ b/c/meterpreter/source/extensions/stdapi/server/fs/fs_posix.c @@ -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; +} diff --git a/c/meterpreter/source/extensions/stdapi/server/fs/fs_util.c b/c/meterpreter/source/extensions/stdapi/server/fs/fs_util.c deleted file mode 100644 index 588298b5..00000000 --- a/c/meterpreter/source/extensions/stdapi/server/fs/fs_util.c +++ /dev/null @@ -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 - } -} diff --git a/c/meterpreter/source/extensions/stdapi/server/fs/fs_win.c b/c/meterpreter/source/extensions/stdapi/server/fs/fs_win.c new file mode 100644 index 00000000..ada29181 --- /dev/null +++ b/c/meterpreter/source/extensions/stdapi/server/fs/fs_win.c @@ -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; +} diff --git a/c/meterpreter/source/extensions/stdapi/server/stdapi.c b/c/meterpreter/source/extensions/stdapi/server/stdapi.c index 0e1dde40..6ffcd3fc 100644 --- a/c/meterpreter/source/extensions/stdapi/server/stdapi.c +++ b/c/meterpreter/source/extensions/stdapi/server/stdapi.c @@ -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; } diff --git a/c/meterpreter/source/extensions/stdapi/stdapi.h b/c/meterpreter/source/extensions/stdapi/stdapi.h index 52e7e36a..45b4f0ae 100644 --- a/c/meterpreter/source/extensions/stdapi/stdapi.h +++ b/c/meterpreter/source/extensions/stdapi/stdapi.h @@ -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 ) diff --git a/c/meterpreter/source/server/posix/remote_dispatch.c b/c/meterpreter/source/server/posix/remote_dispatch.c index 6873c635..c004cf7a 100644 --- a/c/meterpreter/source/server/posix/remote_dispatch.c +++ b/c/meterpreter/source/server/posix/remote_dispatch.c @@ -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) diff --git a/c/meterpreter/source/server/remote_dispatch_common.c b/c/meterpreter/source/server/remote_dispatch_common.c index a044e886..f8e9c1fa 100644 --- a/c/meterpreter/source/server/remote_dispatch_common.c +++ b/c/meterpreter/source/server/remote_dispatch_common.c @@ -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); } diff --git a/c/meterpreter/source/server/win/remote_dispatch.c b/c/meterpreter/source/server/win/remote_dispatch.c index 68148bfe..2f3588bc 100644 --- a/c/meterpreter/source/server/win/remote_dispatch.c +++ b/c/meterpreter/source/server/win/remote_dispatch.c @@ -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 * ------------ diff --git a/c/meterpreter/workspace/ext_server_stdapi/Makefile b/c/meterpreter/workspace/ext_server_stdapi/Makefile index 8c59c9de..9e18aa12 100644 --- a/c/meterpreter/workspace/ext_server_stdapi/Makefile +++ b/c/meterpreter/workspace/ext_server_stdapi/Makefile @@ -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 \ diff --git a/c/meterpreter/workspace/ext_server_stdapi/ext_server_stdapi.vcxproj b/c/meterpreter/workspace/ext_server_stdapi/ext_server_stdapi.vcxproj index f41ef2c1..859a89cb 100644 --- a/c/meterpreter/workspace/ext_server_stdapi/ext_server_stdapi.vcxproj +++ b/c/meterpreter/workspace/ext_server_stdapi/ext_server_stdapi.vcxproj @@ -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> \ No newline at end of file +</Project>