diff --git a/c/meterpreter/source/extensions/stdapi/server/fs/fs_win.c b/c/meterpreter/source/extensions/stdapi/server/fs/fs_win.c index 8f0c750e..2ebcb1db 100644 --- a/c/meterpreter/source/extensions/stdapi/server/fs/fs_win.c +++ b/c/meterpreter/source/extensions/stdapi/server/fs/fs_win.c @@ -5,7 +5,7 @@ BOOL DeleteFolderWR(LPCWSTR szPath) { - WIN32_FIND_DATAW FindFileData; + WIN32_FIND_DATAW findFileData; HANDLE hFind = INVALID_HANDLE_VALUE; DWORD dwError, dwAttrs; BOOL bRes; @@ -51,7 +51,7 @@ BOOL DeleteFolderWR(LPCWSTR szPath) else wsprintfW(cPath, L"%s\\*.*", szPath); - hFind = FindFirstFileW(cPath, &FindFileData); + hFind = FindFirstFileW(cPath, &findFileData); if (hFind == INVALID_HANDLE_VALUE) return FALSE; @@ -62,22 +62,22 @@ BOOL DeleteFolderWR(LPCWSTR szPath) do { - if (lstrcmpiW(FindFileData.cFileName, L".") == 0 || lstrcmpiW(FindFileData.cFileName, L"..") == 0) + if (lstrcmpiW(findFileData.cFileName, L".") == 0 || lstrcmpiW(findFileData.cFileName, L"..") == 0) continue; - if (lstrlenW(cPath) + lstrlenW(L"\\") + lstrlenW(FindFileData.cFileName) + 1 > MAX_PATH) + if (lstrlenW(cPath) + lstrlenW(L"\\") + lstrlenW(findFileData.cFileName) + 1 > MAX_PATH) continue; - wsprintfW(cCurrentFile, L"%s\\%s", cPath, FindFileData.cFileName); - if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + wsprintfW(cCurrentFile, L"%s\\%s", cPath, findFileData.cFileName); + if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_READONLY) + if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_READONLY) { - FindFileData.dwFileAttributes &= ~FILE_ATTRIBUTE_READONLY; - SetFileAttributesW(cCurrentFile, FindFileData.dwFileAttributes); + findFileData.dwFileAttributes &= ~FILE_ATTRIBUTE_READONLY; + SetFileAttributesW(cCurrentFile, findFileData.dwFileAttributes); } - if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) + if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) bRes = RemoveDirectoryW(cCurrentFile); else bRes = DeleteFolderWR(cCurrentFile); @@ -85,13 +85,13 @@ BOOL DeleteFolderWR(LPCWSTR szPath) else { - if ((FindFileData.dwFileAttributes & FILE_ATTRIBUTE_READONLY) || - (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)) + if ((findFileData.dwFileAttributes & FILE_ATTRIBUTE_READONLY) || + (findFileData.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)) SetFileAttributesW(cCurrentFile, FILE_ATTRIBUTE_NORMAL); DeleteFileW(cCurrentFile); } - } while (FindNextFileW(hFind, &FindFileData)); + } while (FindNextFileW(hFind, &findFileData)); dwError = GetLastError(); @@ -268,6 +268,12 @@ int fs_delete_file(const char *path) goto out; } + DWORD attrs = GetFileAttributesW(path_w); + if ((attrs != INVALID_FILE_ATTRIBUTES) && (attrs & FILE_ATTRIBUTE_READONLY)) { + attrs &= ~FILE_ATTRIBUTE_READONLY; + SetFileAttributesW(path_w, attrs); + } + if (DeleteFileW(path_w) == 0) { rc = GetLastError(); } diff --git a/php/meterpreter/ext_server_stdapi.php b/php/meterpreter/ext_server_stdapi.php index f4c8edc3..07233186 100755 --- a/php/meterpreter/ext_server_stdapi.php +++ b/php/meterpreter/ext_server_stdapi.php @@ -278,8 +278,8 @@ function array_prepend($array, $string, $deep=false) { ## END Search Helpers -if (!function_exists('cononicalize_path')) { -function cononicalize_path($path) { +if (!function_exists('canonicalize_path')) { +function canonicalize_path($path) { $path = str_replace(array("/", "\\"), DIRECTORY_SEPARATOR, $path); return $path; } @@ -288,7 +288,7 @@ function cononicalize_path($path) { # # Need to nail down what this should actually do. Ruby's File.expand_path is -# for cononicalizing a path (e.g., removing /./ and ../) and expanding "~" into +# for canonicalizing a path (e.g., removing /./ and ../) and expanding "~" into # a path to the current user's homedir. In contrast, Meterpreter has # traditionally used this to get environment variables from the server. # @@ -336,7 +336,7 @@ register_command('stdapi_fs_delete_dir'); function stdapi_fs_delete_dir($req, &$pkt) { my_print("doing rmdir"); $path_tlv = packet_get_tlv($req, TLV_TYPE_DIRECTORY_PATH); - $ret = @rmdir(cononicalize_path($path_tlv['value'])); + $ret = @rmdir(canonicalize_path($path_tlv['value'])); return $ret ? ERROR_SUCCESS : ERROR_FAILURE; } } @@ -346,7 +346,7 @@ register_command('stdapi_fs_mkdir'); function stdapi_fs_mkdir($req, &$pkt) { my_print("doing mkdir"); $path_tlv = packet_get_tlv($req, TLV_TYPE_DIRECTORY_PATH); - $ret = @mkdir(cononicalize_path($path_tlv['value'])); + $ret = @mkdir(canonicalize_path($path_tlv['value'])); return $ret ? ERROR_SUCCESS : ERROR_FAILURE; } } @@ -357,7 +357,7 @@ register_command('stdapi_fs_chdir'); function stdapi_fs_chdir($req, &$pkt) { my_print("doing chdir"); $path_tlv = packet_get_tlv($req, TLV_TYPE_DIRECTORY_PATH); - $ret = @chdir(cononicalize_path($path_tlv['value'])); + $ret = @chdir(canonicalize_path($path_tlv['value'])); return $ret ? ERROR_SUCCESS : ERROR_FAILURE; } } @@ -368,7 +368,11 @@ register_command('stdapi_fs_delete'); function stdapi_fs_delete($req, &$pkt) { my_print("doing delete"); $path_tlv = packet_get_tlv($req, TLV_TYPE_FILE_NAME); - $ret = @unlink(cononicalize_path($path_tlv['value'])); + $path = canonicalize_path($path_tlv['value']); + if (is_windows()) { + exec("attrib.exe -r ".$path); + } + $ret = @unlink($path) return $ret ? ERROR_SUCCESS : ERROR_FAILURE; } } @@ -380,8 +384,8 @@ function stdapi_fs_file_move($req, &$pkt) { my_print("doing mv"); $old_file_tlv = packet_get_tlv($req, TLV_TYPE_FILE_NAME); $new_file_tlv = packet_get_tlv($req, TLV_TYPE_FILE_PATH); - $old_file = cononicalize_path($old_file_tlv['value']); - $new_file = cononicalize_path($new_file_tlv['value']); + $old_file = canonicalize_path($old_file_tlv['value']); + $new_file = canonicalize_path($new_file_tlv['value']); $ret = @rename($old_file, $new_file); return $ret ? ERROR_SUCCESS : ERROR_FAILURE; } @@ -394,8 +398,8 @@ function stdapi_fs_file_copy($req, &$pkt) { my_print("doing cp"); $old_file_tlv = packet_get_tlv($req, TLV_TYPE_FILE_NAME); $new_file_tlv = packet_get_tlv($req, TLV_TYPE_FILE_PATH); - $old_file = cononicalize_path($old_file_tlv['value']); - $new_file = cononicalize_path($new_file_tlv['value']); + $old_file = canonicalize_path($old_file_tlv['value']); + $new_file = canonicalize_path($new_file_tlv['value']); $ret = @copy($old_file, $new_file); return $ret ? ERROR_SUCCESS : ERROR_FAILURE; } @@ -418,7 +422,7 @@ register_command('stdapi_fs_ls'); function stdapi_fs_ls($req, &$pkt) { my_print("doing ls"); $path_tlv = packet_get_tlv($req, TLV_TYPE_DIRECTORY_PATH); - $path = cononicalize_path($path_tlv['value']); + $path = canonicalize_path($path_tlv['value']); $dir_handle = @opendir($path); if ($dir_handle) { @@ -467,7 +471,7 @@ register_command('stdapi_fs_stat'); function stdapi_fs_stat($req, &$pkt) { my_print("doing stat"); $path_tlv = packet_get_tlv($req, TLV_TYPE_FILE_PATH); - $path = cononicalize_path($path_tlv['value']); + $path = canonicalize_path($path_tlv['value']); $st = stat($path); if ($st) { @@ -500,7 +504,7 @@ register_command('stdapi_fs_delete_file'); function stdapi_fs_delete_file($req, &$pkt) { my_print("doing delete"); $path_tlv = packet_get_tlv($req, TLV_TYPE_FILE_PATH); - $path = cononicalize_path($path_tlv['value']); + $path = canonicalize_path($path_tlv['value']); if ($path && is_file($path)) { $worked = @unlink($path); @@ -517,9 +521,9 @@ function stdapi_fs_search($req, &$pkt) { my_print("doing search"); $root_tlv = packet_get_tlv($req, TLV_TYPE_SEARCH_ROOT); - $root = cononicalize_path($root_tlv['value']); + $root = canonicalize_path($root_tlv['value']); $glob_tlv = packet_get_tlv($req, TLV_TYPE_SEARCH_GLOB); - $glob = cononicalize_path($glob_tlv['value']); + $glob = canonicalize_path($glob_tlv['value']); $recurse_tlv = packet_get_tlv($req, TLV_TYPE_SEARCH_RECURSE); $recurse = $recurse_tlv['value']; @@ -555,7 +559,7 @@ if (!function_exists('stdapi_fs_md5')) { register_command("stdapi_fs_md5"); function stdapi_fs_md5($req, &$pkt) { $path_tlv = packet_get_tlv($req, TLV_TYPE_FILE_PATH); - $path = cononicalize_path($path_tlv['value']); + $path = canonicalize_path($path_tlv['value']); if (is_callable("md5_file")) { $md5 = md5_file($path); @@ -573,7 +577,7 @@ if (!function_exists('stdapi_fs_sha1')) { register_command("stdapi_fs_sha1"); function stdapi_fs_sha1($req, &$pkt) { $path_tlv = packet_get_tlv($req, TLV_TYPE_FILE_PATH); - $path = cononicalize_path($path_tlv['value']); + $path = canonicalize_path($path_tlv['value']); if (is_callable("sha1_file")) { $sha1 = sha1_file($path); diff --git a/python/meterpreter/ext_server_stdapi.py b/python/meterpreter/ext_server_stdapi.py index 7f72a366..cb9e0c32 100644 --- a/python/meterpreter/ext_server_stdapi.py +++ b/python/meterpreter/ext_server_stdapi.py @@ -1220,8 +1220,10 @@ def stdapi_fs_chdir(request, response): @register_function def stdapi_fs_delete(request, response): - file_path = packet_get_tlv(request, TLV_TYPE_FILE_NAME)['value'] - os.unlink(unicode(file_path)) + file_path = unicode(packet_get_tlv(request, TLV_TYPE_FILE_NAME)['value']) + if has_windll: + subprocess.call(unicode("attrib.exe -r ") + file_path) + os.unlink(file_path) return ERROR_SUCCESS, response @register_function @@ -1238,6 +1240,8 @@ def stdapi_fs_delete_dir(request, response): @register_function def stdapi_fs_delete_file(request, response): file_path = packet_get_tlv(request, TLV_TYPE_FILE_PATH)['value'] + if has_windll: + subprocess.call(unicode("attrib.exe -r ") + file_path) os.unlink(unicode(file_path)) return ERROR_SUCCESS, response