无法使用我的代码修改我拥有的 Process DACL,但 Process Hacker 可以

Cannot modify Process DACL that I own with my code but Process Hacker can

我有一个进程(我们称之为 ProcessX),默认情况下 运行s 只有 TerminateSynchronizeQuery Limited Information权限。

当我在 Process Hacker 中查看 ProcessX 时,我可以看到权限(ACE、所有者等)。我可以看到我是 ProcessX 的所有者,我可以看到与之关联的 3 个有限权限(TerminateSynchronizeQuery Limited Information),我什至可以编辑权限(例如,在上面设置 Full Control)。

但是,当我 运行 下面的代码检查 ProcessX 的 DACL 时,与拥有 ProcessX[=51= 的同一用户], 我在 GetSecurityInfo() 函数上收到错误代码 5(拒绝访问)。

ProcessX 上使用 AccessChk 和 Process Explorer 的结果相同。

但是,Process Hacker 完全能够读取 ProcessX 的 DACL 并对其进行修改。

我不明白。这怎么可能?为什么我的代码无法读取 ProcessX 的 DACL?

我在 MS 文档中读到要读取 DACL,我必须使用 OpenProcess()READ_CONTROL

但是 READ_CONTROL 不是我的用户的流程中可用的 ACE。所以,我无法用它打开进程(如果我尝试 OpenProcess() 错误,这是合乎逻辑的)。

所以,我是进程的所有者,但我不能修改 ACE,但 Process Hacker 可以。

谁能帮我理解一下?

#include <windows.h>
#include <accctrl.h>
#include <aclapi.h>
#include <winnt.h>
#include <stdio.h>
#include <lmcons.h>


DWORD AddAceToObjectsSecurityDescriptor (
    HANDLE pszObjName,          // name of object
    SE_OBJECT_TYPE ObjectType,  // type of object
    LPTSTR pszTrustee,          // trustee for new ACE
    TRUSTEE_FORM TrusteeForm,   // format of trustee structure
    DWORD dwAccessRights,       // access mask for new ACE
    ACCESS_MODE AccessMode,     // type of ACE
    DWORD dwInheritance         // inheritance flags for new ACE
) 
{
    DWORD dwRes = 0;
    PACL pOldDACL = NULL, pNewDACL = NULL;
    PSECURITY_DESCRIPTOR pSD = NULL;
    EXPLICIT_ACCESS ea;

    if (NULL == pszObjName) 
        return ERROR_INVALID_PARAMETER;

    //retrieve user
    char username[UNLEN+1];
    DWORD username_len = UNLEN+1;
    GetUserName(username, &username_len);
    printf(username);

    // Get a pointer to the existing DACL.

    dwRes = GetSecurityInfo(pszObjName, ObjectType, 
          DACL_SECURITY_INFORMATION,
          NULL, NULL, &pOldDACL, NULL, &pSD);
    if (ERROR_SUCCESS != dwRes) {
        printf( "GetSecurityInfo Error %u\n", dwRes );
        goto Cleanup; 
    }  

    // Initialize an EXPLICIT_ACCESS structure for the new ACE. 

    ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));
    ea.grfAccessPermissions = dwAccessRights;
    ea.grfAccessMode = AccessMode;
    ea.grfInheritance= dwInheritance;
    ea.Trustee.TrusteeForm = TrusteeForm;
    ea.Trustee.ptstrName = pszTrustee;

    // Create a new ACL that merges the new ACE
    // into the existing DACL.

    dwRes = SetEntriesInAcl(1, &ea, pOldDACL, &pNewDACL);
    if (ERROR_SUCCESS != dwRes)  {
        printf( "SetEntriesInAcl Error %u\n", dwRes );
        goto Cleanup; 
    }  

    // Attach the new ACL as the object's DACL.

    dwRes = SetSecurityInfo(pszObjName, ObjectType, 
          DACL_SECURITY_INFORMATION,
          NULL, NULL, pNewDACL, NULL);
    if (ERROR_SUCCESS != dwRes)  {
        printf( "SetSecurityInfo Error %u\n", dwRes );
        goto Cleanup; 
    }  

    Cleanup:

        if(pSD != NULL) 
            LocalFree((HLOCAL) pSD); 
        if(pNewDACL != NULL) 
            LocalFree((HLOCAL) pNewDACL); 

        return dwRes;
}

int main(int argc, char *argv[])
{
  int pid = atoi(argv[1]);
  printf("[+] Ensuring we have the proper privs....\n");
  HANDLE self = OpenProcess(
  PROCESS_TERMINATE | PROCESS_QUERY_LIMITED_INFORMATION | SYNCHRONIZE,
  FALSE, (DWORD) pid);
  if(self != NULL){
    printf("process open !\n"); 
    AddAceToObjectsSecurityDescriptor(self, SE_KERNEL_OBJECT, (LPSTR)"S-1-5-21-BLABLALEAKBLALBLA",TRUSTEE_IS_SID, PROCESS_ALL_ACCESS, GRANT_ACCESS, 0);
  }
  else{
      printf("error in opening of the process\n");
  }
}

问题已解决!

我假设 READ_CONTROL 将被拒绝,因为它在 运行 进程的 DACL 上不可用。

事实证明,当您拥有一个对象时,您对它拥有隐式 READ_CONTROLWRITE_DAC 权限,即使为拥有它的用户在该对象上设置了零 ACE。

#include <windows.h>
#include <accctrl.h>
#include <aclapi.h>
#include <winnt.h>
#include <stdio.h>
#include <lmcons.h>



DWORD AddAceToObjectsSecurityDescriptor (
    HANDLE pszObjName,          // name of object
    SE_OBJECT_TYPE ObjectType,  // type of object
    LPTSTR pszTrustee,          // trustee for new ACE
    TRUSTEE_FORM TrusteeForm,   // format of trustee structure
    DWORD dwAccessRights,       // access mask for new ACE
    ACCESS_MODE AccessMode,     // type of ACE
    DWORD dwInheritance         // inheritance flags for new ACE
) 
{
    DWORD dwRes = 0;
    PACL pOldDACL = NULL, pNewDACL = NULL;
    PSECURITY_DESCRIPTOR pSD = NULL;
    EXPLICIT_ACCESS ea;

    if (NULL == pszObjName) 
        return ERROR_INVALID_PARAMETER;


    // Get a pointer to the existing DACL.

    dwRes = GetSecurityInfo(pszObjName, ObjectType, 
          DACL_SECURITY_INFORMATION,
          NULL, NULL, &pOldDACL, NULL, &pSD);
    if (ERROR_SUCCESS != dwRes) {
        printf( "GetSecurityInfo Error %u\n", dwRes );
        goto Cleanup; 
    }  

    // Initialize an EXPLICIT_ACCESS structure for the new ACE. 

    ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));
    ea.grfAccessPermissions = dwAccessRights;
    ea.grfAccessMode = AccessMode;
    ea.grfInheritance= dwInheritance;
    ea.Trustee.TrusteeForm = TrusteeForm;
    ea.Trustee.ptstrName = pszTrustee;

    // Create a new ACL that merges the new ACE
    // into the existing DACL.

    dwRes = SetEntriesInAcl(1, &ea, pOldDACL, &pNewDACL);
    if (ERROR_SUCCESS != dwRes)  {
        printf( "SetEntriesInAcl Error %u\n", dwRes );
        goto Cleanup; 
    }else{
      printf("SetEntriesAcl SUCCESS !\n");
    }  

    // Attach the new ACL as the object's DACL.

    dwRes = SetSecurityInfo(pszObjName, ObjectType, 
          DACL_SECURITY_INFORMATION,
          NULL, NULL, pNewDACL, NULL);
    if (ERROR_SUCCESS != dwRes)  {
        printf( "SetSecurityInfo Error %u\n", dwRes );
        goto Cleanup; 
    }else{
      printf("SetSecurityInfo SUCCESS \n");
    }  

    Cleanup:

        if(pSD != NULL) 
            LocalFree((HLOCAL) pSD); 
        if(pNewDACL != NULL) 
            LocalFree((HLOCAL) pNewDACL); 

        return dwRes;
}

int main(int argc, char *argv[])
{
  int pid = atoi(argv[1]);
  DWORD dwRes = 0;

  char username[UNLEN+1];
  DWORD username_len = UNLEN+1;
  GetUserName(username, &username_len);

  HANDLE self = OpenProcess(READ_CONTROL | WRITE_DAC, FALSE, (DWORD) pid);
  if(self != NULL){
    printf("process open !\n"); 
    AddAceToObjectsSecurityDescriptor(self, SE_KERNEL_OBJECT, (LPSTR)username,TRUSTEE_IS_NAME, PROCESS_ALL_ACCESS, GRANT_ACCESS, 0);
  }
  else{
      dwRes = GetLastError();
      printf("error in opening of the process. Code %u \n", dwRes);
  }
}