diff --git a/data/meterpreter/ext_server_stdapi.lso b/data/meterpreter/ext_server_stdapi.lso index 4ecfd7c3dd..3d1cf9ba1a 100755 Binary files a/data/meterpreter/ext_server_stdapi.lso and b/data/meterpreter/ext_server_stdapi.lso differ diff --git a/external/source/meterpreter/source/extensions/stdapi/server/fs/dir.c b/external/source/meterpreter/source/extensions/stdapi/server/fs/dir.c index a951fe6b44..b27829e50f 100644 --- a/external/source/meterpreter/source/extensions/stdapi/server/fs/dir.c +++ b/external/source/meterpreter/source/extensions/stdapi/server/fs/dir.c @@ -21,7 +21,7 @@ DWORD request_fs_ls(Remote *remote, Packet *packet) LPSTR expanded = NULL, tempFile = NULL; DWORD tempFileSize = 0; LPSTR baseDirectory = NULL; - struct stat buf; + struct meterp_stat buf; directory = packet_get_tlv_value_string(packet, TLV_TYPE_DIRECTORY_PATH); @@ -150,7 +150,7 @@ DWORD request_fs_ls(Remote *remote, Packet *packet) tempFile); // Stat the file to get more information about it. - if (stat(tempFile, &buf) >= 0) + if (fs_stat(tempFile, &buf) >= 0) packet_add_tlv_raw(response, TLV_TYPE_STAT_BUF, &buf, sizeof(buf)); diff --git a/external/source/meterpreter/source/extensions/stdapi/server/fs/file.c b/external/source/meterpreter/source/extensions/stdapi/server/fs/file.c index 1efd25f7a7..121bc06345 100644 --- a/external/source/meterpreter/source/extensions/stdapi/server/fs/file.c +++ b/external/source/meterpreter/source/extensions/stdapi/server/fs/file.c @@ -257,7 +257,7 @@ DWORD request_fs_separator(Remote *remote, Packet *packet) DWORD request_fs_stat(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); - struct stat buf; + struct meterp_stat buf; LPCSTR filePath; LPSTR expanded = NULL; DWORD result = ERROR_SUCCESS; @@ -273,7 +273,7 @@ DWORD request_fs_stat(Remote *remote, Packet *packet) { // Stat the file using the Microsoft stat wrapper so that we don't have to // do translations - if (stat(expanded, &buf) < 0) + if (fs_stat(expanded, &buf) < 0) result = GetLastError(); else packet_add_tlv_raw(response, TLV_TYPE_STAT_BUF, &buf, diff --git a/external/source/meterpreter/source/extensions/stdapi/server/fs/fs.h b/external/source/meterpreter/source/extensions/stdapi/server/fs/fs.h index 210d3e9a3b..9de024c660 100644 --- a/external/source/meterpreter/source/extensions/stdapi/server/fs/fs.h +++ b/external/source/meterpreter/source/extensions/stdapi/server/fs/fs.h @@ -24,4 +24,33 @@ DWORD request_fs_sha1(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/external/source/meterpreter/source/extensions/stdapi/server/fs/fs_util.c b/external/source/meterpreter/source/extensions/stdapi/server/fs/fs_util.c index 8a2c2e123f..355c7da5e7 100644 --- a/external/source/meterpreter/source/extensions/stdapi/server/fs/fs_util.c +++ b/external/source/meterpreter/source/extensions/stdapi/server/fs/fs_util.c @@ -1,4 +1,5 @@ #include "precomp.h" +#include "fs.h" /* * Returns an expanded file path that must be freed @@ -37,4 +38,31 @@ LPSTR fs_expand_path(LPCSTR regular) strcpy(expandedFilePath, regular); return expandedFilePath; #endif -} \ No newline at end of file +} + +/* + * 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 { + return ret; + } +}