列出系统中所有 DCOM 及其访问权限

最近有一个需求是要查看系统中某些 DCOM 组件的访问权限,索性就写个程序把所有的可被外部拉起的组件都列一下。由于之前并没有接触过这一方面的内容,所以还是有很多问题亟待解决(虽然并不难~)

程序的思路就是遍历 HKEY_CLASSES_ROOT\\CLSID 注册表项下所有的子键和键值,其中拥有子键 LocalServer32 的表明其可以被其他进程拉起,拥有键值 AppId 的表明其是一个 DCOM。转到对应 HKEY_CLASSES_ROOT\\APPID 表项下去查看 AccessPermissionLaunchPermission 键值。

AccessPermissionLaunchPermission 的键值是编码转换后的二进制,其实际上是一个 SECURITY_INFORMATION 结构,包含了对象的 Ownerprimary group、discretionary access control list、system access control list 信息。为了方便查看需要将其转化为字符串的形式。


#include  
#include  
#include 
#include   
#include   
#include 
#include 
#include 


#define MAX_KEY_LENGTH 255  
#define MAX_VALUE_NAME 16383  
#define MAX_ACL_LENGTH 255
#define SUCCESS_CHECK(hr) if(hr != ERROR_SUCCESS){printf("RegQuery Error!!\n");return;}

DWORD dwType = REG_BINARY | REG_DWORD | REG_EXPAND_SZ | REG_MULTI_SZ | REG_NONE | REG_SZ;
std::queue keystack;

//#define COMMAND_OUTPUT

FILE *fp;

BOOL GetRegData(HKEY rootKey, const wchar_t* path, wchar_t* value, unsigned char* lpData)
{
    HKEY hKey;
    BOOL rlt = FALSE;
    if (RegOpenKeyEx(rootKey, path, 0, KEY_READ, &hKey) != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        return NULL;
    }
    
    DWORD ret;
    DWORD dwType;
    DWORD dwNameLen = 255;
    ret = RegQueryValueEx(hKey, value, 0, &dwType, lpData, &dwNameLen);
    if (ret == ERROR_SUCCESS)
    {
        rlt = TRUE;
        
    }
    return rlt;
}

void QueryAppIdPermission(HKEY rootKey, const wchar_t* path)
{
    BYTE cbAPermission[255] = { 0 };
    LPWSTR lpAPermission[1] = {0};
    if (GetRegData(rootKey, path, L"AccessPermission", cbAPermission))
    {
        ConvertSecurityDescriptorToStringSecurityDescriptor((PSECURITY_DESCRIPTOR)cbAPermission, SDDL_REVISION_1, DACL_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION, lpAPermission, NULL);
        fwprintf(fp, L" AccessPermission: %s\n", lpAPermission[0]);
    }

    BYTE cbLPermission[255] = { 0 };
    LPWSTR lpLPermission[1] = { 0 };
    if (GetRegData(rootKey, path, L"LaunchPermission", cbLPermission))
    {
        ConvertSecurityDescriptorToStringSecurityDescriptor((PSECURITY_DESCRIPTOR)cbLPermission, SDDL_REVISION_1, DACL_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION, lpLPermission, NULL);
        fwprintf(fp, L" LaunchPermission: %s\n", lpLPermission[0]);
    }
}

BOOL IsLocalServer(HKEY rootKey, const wchar_t* path)
{
    BOOL rlt = FALSE;
    HKEY hKey;
    

    TCHAR    achKey[MAX_KEY_LENGTH];   // buffer for subkey name   
    DWORD    cSubKeys = 0;               // number of subkeys      
    DWORD    cName;                   // size of name string   
    DWORD    i, retCode;

    std::wstring newPath = L"";
    newPath.append(path);
    newPath.append(L"\\LocalServer32");

    if (RegOpenKeyEx(rootKey, newPath.c_str(), 0, KEY_READ, &hKey) == ERROR_SUCCESS)
    {
        
        rlt = TRUE;
    }
    RegCloseKey(hKey);
    return rlt;
}

BOOL IsDComponent(HKEY rootKey, const wchar_t* path)
{
    BOOL   rlt = FALSE;

    BYTE szBuffer[255] = { 0 };

    if (GetRegData(rootKey, path, L"AppID", szBuffer))
    {
        rlt = TRUE;
    }
    return rlt;
}

void regQuery(HKEY rootKey, const wchar_t* path)
{
#ifdef COMMAND_OUTPUT
    _tprintf(TEXT("\nProcess: %s :\n"), path);
#endif
    HKEY hKey;
    if (RegOpenKeyEx(rootKey, path, 0, KEY_READ, &hKey) != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        return;
    }

    TCHAR    achKey[MAX_KEY_LENGTH];   // buffer for subkey name  
    DWORD    cbName;                   // size of name string   
    TCHAR    achClass[MAX_PATH] = TEXT("");  // buffer for class name   
    DWORD    cchClassName = MAX_PATH;  // size of class string   
    DWORD    cSubKeys = 0;               // number of subkeys   
    DWORD    cbMaxSubKey;              // longest subkey size   
    DWORD    cchMaxClass;              // longest class string   
    DWORD    cValues;              // number of values for key   
    DWORD    cchMaxValue;          // longest value name   
    DWORD    cbMaxValueData;       // longest value data   
    DWORD    cbSecurityDescriptor; // size of security descriptor   
    FILETIME ftLastWriteTime;      // last write time   

    DWORD i, retCode;

    // Get the class name and the value count.   
    retCode = RegQueryInfoKey(
        hKey,                    // key handle   
        achClass,                // buffer for class name   
        &cchClassName,           // size of class string   
        NULL,                    // reserved   
        &cSubKeys,               // number of subkeys   
        &cbMaxSubKey,            // longest subkey size   
        &cchMaxClass,            // longest class string   
        &cValues,                // number of values for this key   
        &cchMaxValue,            // longest value name   
        &cbMaxValueData,         // longest value data   
        &cbSecurityDescriptor,   // security descriptor   
        &ftLastWriteTime);       // last write time   

                                 // Enumerate the subkeys, until RegEnumKeyEx fails.  
    if (cSubKeys)
    {
#ifdef COMMAND_OUTPUT
        printf("Number of subkeys: %d\n", cSubKeys);
#endif
        for (i = 0; i

部分结果如下所示

CLSID : {F87B28F1-DA9A-4F35-8EC0-800EFCF26B83}
    ProgId: SPPUI.SPPUIObjectInteractive.1
    AppId: {0868DC9B-D9A2-4f64-9362-133CEA201299}
    AccessPermission: O:BAG:BAD:(A;;CCDCLC;;;PS)(A;;CCDCLC;;;SY)
    LaunchPermission: O:BAG:BAD:(A;;CCDCLCSWRP;;;WD)

其中 AccessPermission 就是格式化为字符串之后的 Security Descriptor 其结构如下

O:owner_sid
G:group_sid
D:dacl_flags(string_ace1)(string_ace2)... (string_acen)
S:sacl_flags(string_ace1)(string_ace2)... (string_acen)

其中的 sidace等都是以两个大写字母表示的值,当然也可以直接使用标准值,具体的细节可以查看 文档
因此上述 CLSID 的 AccessPermission 解释出来为

AccessPermission: O:BAG:BAD:(A;;CCDCLC;;;PS)(A;;CCDCLC;;;SY)

Owner: SDDL_BUILTIN_ADMINISTRATORS    S-1-5-32-544
Group: SDDL_BUILTIN_ADMINISTRATORS    S-1-5-32-544
DACL: 
    ACE[00]:
        ace_type : ACCESS_ALLOWED_ACE_TYPE
        ace_flags : 
        rights : 
                ADS_RIGHT_DS_CREATE_CHILD
                ADS_RIGHT_DS_DELETE_CHILD
                ADS_RIGHT_ACTRL_DS_LIST
        object_guid : 
        inherit_object_guid : 
        account_sid : SDDL_PERSONAL_SELF   S-1-5-10
    ACE[01]:
        ace_type : ACCESS_ALLOWED_ACE_TYPE
        ace_flags : 
        rights : 
                ADS_RIGHT_DS_CREATE_CHILD
                ADS_RIGHT_DS_DELETE_CHILD
                ADS_RIGHT_ACTRL_DS_LIST
        object_guid : 
        inherit_object_guid : 
        account_sid : SDDL_LOCAL_SYSTEM S-1-5-18

表示该组件可以被 Sytem 权限或自身访问

你可能感兴趣的:(列出系统中所有 DCOM 及其访问权限)