2016-12-20 5 views
-1

Я хочу знать целостность levef файла, но не могу получить sacl. GetNamedSecurityInfo возвращает 0 (ERROR_SUCCESS), что означает, что нет ошибки при его выполнении, но SACL по-прежнему становится 0x00000000. Кто-нибудь знает, в чем проблема?не может получить sacl файла

int GetFileIntegrityLevel() 
{ 
    DWORD integrityLevel = SECURITY_MANDATORY_UNTRUSTED_RID; 
    PSECURITY_DESCRIPTOR pSD = NULL; 
    PACL acl = 0; 
    int dw = 0; 
     GetNamedSecurityInfoA("C:\\8.docx", SE_FILE_OBJECT, SACL_SECURITY_INFORMATION, 0, 0, 0, &acl, &pSD)); 
    { 
     if (0 != acl && 0 < acl->AceCount) 
     { 
      SYSTEM_MANDATORY_LABEL_ACE* ace = 0; 
      if (GetAce(acl, 0, reinterpret_cast<void**>(&ace))) 
      { 
       SID* sid = reinterpret_cast<SID*>(&ace->SidStart); 
       integrityLevel = sid->SubAuthority[0]; 
      } 
     } 

     PWSTR stringSD; 
     ULONG stringSDLen = 0; 

     ConvertSecurityDescriptorToStringSecurityDescriptor(pSD, SDDL_REVISION_1, ACCESS_SYSTEM_SECURITY, &stringSD, &stringSDLen); 

     if (pSD) 
     { 
      LocalFree(pSD); 
     } 
    } 

    if (integrityLevel == 0x0000) 
     return 0; 
    else if (integrityLevel == 0x1000) 
     return 1; 
    else if (integrityLevel == 0x2000) 
     return 2; 
    else if (integrityLevel == 0x3000) 
     return 3; 
    else if (integrityLevel == 0x4000) 
     return 4; 
    else 
     return -1; 
} 


int main() 
{ 

    HANDLE curProcess = GetCurrentProcess(); 

    TOKEN_PRIVILEGES tp; 
    LUID sdv; 

    HANDLE hToken = 0; 
    OpenProcessToken(curProcess, TOKEN_ADJUST_PRIVILEGES | TOKEN_READ | TOKEN_QUERY, &hToken); 

    LookupPrivilegeValue(NULL, SE_SECURITY_NAME, &sdv); 

    tp.PrivilegeCount = 1; 
    tp.Privileges[0].Luid = sdv; 
    tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 

    AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), (PTOKEN_PRIVILEGES)NULL, 0); 


    int i = GetFileIntegrityLevel(); 

    printf("%d\n", i); 



    printf("%d\n", i); 
    CloseHandle(curProcess); 
    std::cin.get(); 
} 
+2

Практически отсутствует обработка ошибок в коде. Почти любой вызов может потерпеть неудачу, но мы понятия не имеем, если это так или нет. Внесите отчет об ошибках. – IInspectable

ответ

1

вам нужно использовать не SACL_SECURITY_INFORMATION но LABEL_SECURITY_INFORMATION

пример кода:

ULONG GetFileIntegrityLevel(PCWSTR fileName, PULONG pil) 
{ 
    PACL Sacl; 
    PSECURITY_DESCRIPTOR pSD; 
    *pil = SECURITY_MANDATORY_MEDIUM_RID;// default LABEL 

    ULONG err = GetNamedSecurityInfoW(fileName, SE_FILE_OBJECT, LABEL_SECURITY_INFORMATION, 0, 0, 0, &Sacl, &pSD); 

    if (!err) 
    { 
     if (Sacl) 
     { 
      union { 
       PVOID Ace; 
       PSYSTEM_MANDATORY_LABEL_ACE pLabel; 
       PACE_HEADER pHeader; 
      }; 

      err = ERROR_GEN_FAILURE; 

      ACL_SIZE_INFORMATION asi; 

      if (GetAclInformation(Sacl, &asi, sizeof(asi), AclSizeInformation)) 
      { 
       PSID Sid; 

       union { 
        PUCHAR pc; 
        PULONG pl; 
       }; 

       static SID_IDENTIFIER_AUTHORITY LabelAuth = SECURITY_MANDATORY_LABEL_AUTHORITY; 

       switch (asi.AceCount) 
       { 
       case 1: 
        if (GetAce(Sacl, 0, &Ace)) 
        { 
         if (pHeader->AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE) 
         { 
          Sid = &pLabel->SidStart; 

          if (pc = GetSidSubAuthorityCount(Sid)) 
          { 
           if (*pc == 1 && !memcmp(&LabelAuth, GetSidIdentifierAuthority(Sid), sizeof(SID_IDENTIFIER_AUTHORITY))) 
           { 
            if (pl = GetSidSubAuthority(Sid, 0)) 
            { 
             *pil = *pl; 
       case 0: 
             err = ERROR_SUCCESS; 
            } 
           } 
          } 
         } 
        } 
        break; 
       } 
      } 
     } 

     LocalFree(pSD); 
    } 

    return err; 
} 

, несмотря на это SYSTEM_MANDATORY_LABEL_ACE_TYPE находится в SACL - SACL_SECURITY_INFORMATION не возвращает этот ACE - это фильтр SACL и удалить этот тип ACE с выхода. только LABEL_SECURITY_INFORMATION возвращает этот тип ACE - SACL также фильтруется и удаляет все ACE, кроме этого типа. если мы хотим получить не фильтрованный SACL как есть - нужно использовать оба флага - LABEL_SECURITY_INFORMATION|SACL_SECURITY_INFORMATION.

В большинстве случаев файлы/папки не имеют обязательной маркировки вообще. в этом случае по умолчанию - SECURITY_MANDATORY_MEDIUM_RID. поэтому алгоритм следующий - мы запрашиваем этикетку с LABEL_SECURITY_INFORMATION

  • , если файл не не SACL на всех - мы получили NULL ли SacI в выходной - так по умолчанию SECURITY_MANDATORY_MEDIUM_RID
  • , если файл уже SACL, но без этикетки - мы опустел Список SACL в выходной (Sacl != NULL && AceCount == 0) - снова SECURITY_MANDATORY_MEDIUM_RID по умолчанию
  • , если файл имеет обязательный ярлык - мы должны есть ли SacI с AceCount == 1 - нужно извлечь RID форме это ACE

также для SACL_SECURITY_INFORMATION

права, необходимые для запроса: ACCESS_SYSTEM_SECURITY

Право требуется установить: ACCESS_SYSTEM_SECURITY

Чтобы прочитать SACL из дескриптора безопасности, то вызывающий процесс должен быть предоставлен ACCESS_SYSTEM_SECURITY доступ, когда была открыта рукоятка . Надлежащий образ, чтобы получить этот доступ, чтобы позволить SE_SECURITY_NAME привилегии в текущих маркерах вызывающего абонента, откройте ручки для доступа ACCESS_SYSTEM_SECURITY, а затем отключить привилегии

но получил LABEL_SECURITY_INFORMATION нам не нужно иметь/включить любые привилегии, необходимые

Право на запрос: READ_CONTROL

Право требуется установить: WRITE_OWNER

+0

Кроме того, чтобы сделать код немного проще, обеспечивает ли LABEL_SECURITY_INFORMATION любое другое преимущество?Например, означает ли это, что вам не нужны повышенные привилегии? –

+0

@HarryJohnston - действительно немного информации. почти у большинства файлов нет явного ярлыка, поэтому по умолчанию - «MEDIUM». некоторые файлы, например, в 'Users \ \ AppData \ LocalLow' имеют' LOW' - для приложений LowIntegrity могут записываться в это местоположение. 'HIGH' i видят только в корневом каталоге системного диска (например,' c: \\ '), в то время как в других системных папках (например,' c: \ windows' - ​​нет метки, поэтому 'MEDIUM'), на других дисках также нет LABEL. это быстрее полезно для некоторых служебных программ. и, конечно, это ничего не говорит о файле DACL, только для чтения и т. д. – RbMm

+0

@HarryJohnston - «означает ли это, что вам не нужны повышенные привилегии» - да, когда мы его используем, нам не нужно ** 'SE_SECURITY_NAME' привилегия , в отличие от использования 'SACL_SECURITY_INFORMATION'. но главное - даже если объект имеет ярлык в SACL - 'SACL_SECURITY_INFORMATION' - ** не возвращает ** его. ** только ** 'LABEL_SECURITY_INFORMATION' - метка возврата. так что нет другого способа запросить его – RbMm