3

我正在尝试编写一个备份和恢复工具。我在 WinPE CD ( http://en.wikipedia.org/wiki/Windows_Preinstallation_Environment ) 上运行我的代码。我正在尝试读取整个 C: 分区并将其写入网络。就像 tar 命令一样,但特定于 Windows。除了设置文件所有者外,我一切正常。Windows 似乎真的不能容忍未知 SID 拥有的文件。由于我在 WinPE 中运行,因此在 C: 上定义的大多数用户都不在本地用户数据库中。

以下是我尝试过的一些功能:

  • SetFileSecurity(返回 1307)
  • SetSecurityInfo(返回 1307)
  • SetNamedSecurityInfo(返回 1307)
  • 备份写入(返回 1307)
  • NtSetSecurityObject(返回 0xC000005A)

我知道这是可以做到的。SetACL ( http://helgeklein.com/setacl/ ) 能够做到这一点。

所以,问题。如何将文件的所有者设置为不存在的用户/SID?任何帮助是极大的赞赏!

这是我尝试过的代码示例:

#define _WIN32_WINNT 0x0500

#include <windows.h>
#include <sddl.h>
#include <aclapi.h>
#include <tchar.h>

INT _tmain(){

    PSECURITY_DESCRIPTOR psdOwner = LocalAlloc(LPTR,SECURITY_DESCRIPTOR_MIN_LENGTH);

    if (InitializeSecurityDescriptor(psdOwner,SECURITY_DESCRIPTOR_REVISION)){

        PSID psOwner = (PSID)0;

        if (ConvertStringSidToSid(TEXT("S-1-5-21-3626571138-2175758104-1447827851-1013"),&psOwner)){

            if (SetSecurityDescriptorOwner(psdOwner,psOwner,FALSE)){

                DWORD dwError = SetNamedSecurityInfo(TEXT("test.txt"),SE_FILE_OBJECT,OWNER_SECURITY_INFORMATION,psdOwner,NULL,NULL,NULL);

                if (dwError == ERROR_SUCCESS){

                    _tprintf(TEXT("Success!\n"));

                }else{

                    _tprintf(TEXT("Failed to set owner: %u\n"),dwError);

                }

            }else{

                _tprintf(TEXT("Failed to set owner into SD: %u\n"),GetLastError());

            }

        }else{

            _tprintf(TEXT("Failed to covnert Sid string to Sid: %u\n"),GetLastError());

        }

        if (psOwner) LocalFree(psOwner);

    }else{

        _tprintf(TEXT("Failed to initialize SD: %u\n"),GetLastError());

    }

    if (psdOwner) LocalFree(psdOwner);

    return 0;

}
4

1 回答 1

3

原来你需要 SE_RESTORE_NAME 令牌特权。您可以使用以下内容调整您的进程令牌:

BOOL TakeSecurityPriv(LPCTSTR szPriv){

    BOOL bReturn = FALSE;

    HANDLE hProcToken = (HANDLE)0;

    if (OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,&hProcToken)){

        TOKEN_PRIVILEGES tpTokPriv;

        if (LookupPrivilegeValue(NULL,szPriv,&tpTokPriv.Privileges[0].Luid)){

            tpTokPriv.PrivilegeCount = 1;
            tpTokPriv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

            if (AdjustTokenPrivileges(hProcToken,FALSE,&tpTokPriv,0,NULL,0)){

                bReturn = TRUE;

            }

        }

    }

    return bReturn;

}

然后您可以在我的示例中将以下内容添加到 main 的开头:

if (TakeSecurityPriv(SE_RESTORE_NAME)){

这样就消除了 1307 错误。不幸的是,我的示例中还有另一个错误,因为所有者未设置为正确的 SID。但是,当我切换回 BackupRead/BackupWrite 时,我不必创建 SID 或 SECURITY_DESCRIPTOR。我已经考虑了一段时间可能是什么问题,但没有运气。也许其他人可以回答那部分。

于 2013-07-09T03:03:48.210 回答