Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stat files directly to avoid issues with Windows _wstat #195

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 89 additions & 2 deletions c/meterpreter/source/extensions/stdapi/server/fs/fs_win.c
Original file line number Diff line number Diff line change
Expand Up @@ -287,16 +287,103 @@ int fs_fopen(const char *path, const char *mode, FILE **f)
return rc;
}

#define Py_SAFE_DOWNCASTM(VALUE, WIDE, NARROW) (NARROW)(VALUE)

static int
attributes_to_mode(DWORD attr)
{
int m = 0;
if (attr & FILE_ATTRIBUTE_DIRECTORY)
m |= _S_IFDIR | 0111; /* IFEXEC for user,group,other */
else
m |= _S_IFREG;
if (attr & FILE_ATTRIBUTE_READONLY)
m |= 0444;
else
m |= 0666;
return m;
}

static __int64 secs_between_epochs = 11644473600;

static BOOL
attributes_from_dir_w(LPCWSTR pszFile, LPWIN32_FILE_ATTRIBUTE_DATA pfad)
{
HANDLE hFindFile;
WIN32_FIND_DATAW FileData;
hFindFile = FindFirstFileW(pszFile, &FileData);
if (hFindFile == INVALID_HANDLE_VALUE)
return FALSE;
FindClose(hFindFile);
pfad->dwFileAttributes = FileData.dwFileAttributes;
pfad->ftCreationTime = FileData.ftCreationTime;
pfad->ftLastAccessTime = FileData.ftLastAccessTime;
pfad->ftLastWriteTime = FileData.ftLastWriteTime;
pfad->nFileSizeHigh = FileData.nFileSizeHigh;
pfad->nFileSizeLow = FileData.nFileSizeLow;
return TRUE;
}

static void
FILE_TIME_to_time_t_nsec(FILETIME *in_ptr, time_t *time_out)
{
__int64 in;
memcpy(&in, in_ptr, sizeof(in));
*time_out = Py_SAFE_DOWNCASTM((in / 10000000) - secs_between_epochs, __int64, time_t);
}

static int attribute_data_to_stat(WIN32_FILE_ATTRIBUTE_DATA *info, struct meterp_stat *result)
{
memset(result, 0, sizeof(*result));
result->st_mode = attributes_to_mode(info->dwFileAttributes);
result->st_size = (((__int64)info->nFileSizeHigh) << 32) + info->nFileSizeLow;
FILE_TIME_to_time_t_nsec(&info->ftCreationTime, &result->st_ctime);
FILE_TIME_to_time_t_nsec(&info->ftLastWriteTime, &result->st_mtime);
FILE_TIME_to_time_t_nsec(&info->ftLastAccessTime, &result->st_atime);

return 0;
}

static int win32_wstatM(const wchar_t* path, struct meterp_stat *result)
{
int code;
const wchar_t *dot;
WIN32_FILE_ATTRIBUTE_DATA info;
if (!GetFileAttributesExW(path, GetFileExInfoStandard, &info)) {
if (GetLastError() != ERROR_SHARING_VIOLATION) {
return -1;
}
else {
if (!attributes_from_dir_w(path, &info)) {
return -1;
}
}
}
code = attribute_data_to_stat(&info, result);
if (code < 0)
return code;
/* Set IFEXEC if it is an .exe, .bat, ... */
dot = wcsrchr(path, '.');
if (dot) {
if (_wcsicmp(dot, L".bat") == 0 ||
_wcsicmp(dot, L".cmd") == 0 ||
_wcsicmp(dot, L".exe") == 0 ||
_wcsicmp(dot, L".com") == 0)
result->st_mode |= 0111;
}
return code;
}

int fs_stat(char *filename, struct meterp_stat *buf)
{
struct _stat64i32 sbuf;
struct meterp_stat sbuf;

wchar_t *filename_w = utf8_to_wchar(filename);
if (filename_w == NULL) {
return -1;
}

if (_wstat(filename_w, &sbuf) == -1) {
if (win32_wstatM(filename_w, &sbuf) == -1) {
return GetLastError();
}

Expand Down