今日看了看关于windows本身安全机制的一些文章,所以将自己掌握到的一些东西供大家探讨一下。
1. Access Token
windows访问令牌记录着某用户的SID、组ID、Session、及权限等信息,要获取这些信息,可以通过GetTokenInformation API获得。以下是一些代码样例
#define GETATTRI(desc, attri, check) \
if (attri & check)\
{\
if (desc!=_T(""))\
{\
desc += _T(" | ");\
}\
desc+=_T(#check);\
}
#define MAKESIDDESC(type) {type, _T(#type)}
struct SIDNameDesc
{
SID_NAME_USE type;
TCHAR* desc;
};
SIDNameDesc gvSidUseType[]=
{
MAKESIDDESC(SidTypeUser),
MAKESIDDESC(SidTypeGroup),
MAKESIDDESC(SidTypeDomain),
MAKESIDDESC(SidTypeAlias),
MAKESIDDESC(SidTypeWellKnownGroup),
MAKESIDDESC(SidTypeDeletedAccount),
MAKESIDDESC(SidTypeInvalid),
MAKESIDDESC(SidTypeUnknown),
MAKESIDDESC(SidTypeComputer),
MAKESIDDESC(SidTypeLabel),
};
TCHAR* GetSidNameUseDescription(SID_NAME_USE type)
{
TCHAR* pDesc=NULL;
int count = sizeof(gvSidUseType) / sizeof(SIDNameDesc);
for (int i=0;iUser.Sid);
dump(pUser->User.Attributes);
}
void GetTokenGroup(HANDLE hToken)
{
DWORD dwReturnedLen=0;
GetTokenInformation(hToken, TokenGroups, NULL, NULL, &dwReturnedLen);
if (GetLastError()!=ERROR_INSUFFICIENT_BUFFER)
{
cout<<"GetTokenInformation failed with "<GroupCount;i++)
{
dump(pGroup->Groups[i].Sid);
dump(pGroup->Groups[i].Attributes);
cout<PrivilegeCount;i++)
{
dump(pPrivileges->Privileges[i]);
}
}
void GetOwnerInfo(HANDLE hToken)
{
DWORD dwReturnedLen=0;
GetTokenInformation(hToken, TokenOwner, NULL, NULL, &dwReturnedLen);
if (GetLastError()!=ERROR_INSUFFICIENT_BUFFER)
{
cout<<"GetTokenInformation failed with "<Owner);
}
void GetPrimaryGroup(HANDLE hToken)
{
DWORD dwReturnedLen=0;
GetTokenInformation(hToken, TokenPrimaryGroup, NULL, NULL, &dwReturnedLen);
if (GetLastError()!=ERROR_INSUFFICIENT_BUFFER)
{
cout<<"GetTokenInformation failed with "<PrimaryGroup);
}
void Print(LPCSTR desc, LUID luid)
{
LARGE_INTEGER* pli = (LARGE_INTEGER*)&luid;
cout<QuadPart<TokenId);
Print("AuthenticationId", pStatistics->AuthenticationId);
if (pStatistics->TokenType == TokenPrimary)
{
cout<<"Primary Token"<SourceName<SourceIdentifier);
}
void GetTokenSessionID(HANDLE hToken)
{
DWORD dwReturnedLen=0;
DWORD sessionID;
if(!GetTokenInformation(hToken, TokenSessionId, &sessionID, sizeof(DWORD), &dwReturnedLen))
{
cout<<"GetTokenInformation failed with "<
大家知道在Win7上管理员登录后会关联两个Access Token,一个是有管理员权限的Access Token,另外一个是被限制权限的Access Token,其中Restricted Access Token中Administrators组的属性为SE_GROUP_USE_FOR_DENY_ONLY,说明系统在访问检查时,只会检查给这个组应用了拒绝访问的那些ACE项,而允许访问的ACE项被忽略。而CheckTokenMembership在判断一个Token是否属于某个组时,这个组必须存在并且组属性包含SE_GROUP_ENABLED,才会认为这个Token属于这个组。所以一个权限未提升的进程的令牌是不会认为属于Administrators组的。
2. 安全描述符
安全描述符是windows安全对象管理的一种数据结构,用来描述允许什么用户使用某种权限访问它,拒绝什么用户使用某种权限访问它。(另外还有一些审计操作,不讨论了)。获取ACE信息,见一些代码
void ParseAce(PACE_HEADER pAceHdr);
#define GETATTRI(mask, check) \
if (mask & check)\
{\
cout<<#check<Mask);
dump((PSID)&pAllowedAce->SidStart);
}
void ParseAce(PACCESS_DENIED_ACE pAllowedAce)
{
dumpAccessMask(pAllowedAce->Mask);
dump((PSID)&pAllowedAce->SidStart);
}
void ParseAce(PSYSTEM_ALARM_OBJECT_ACE pAllowedAce)
{
}
void ParseAce(PSYSTEM_ALARM_ACE pAllowedAce)
{
}
void ParseAce(PSYSTEM_ALARM_CALLBACK_ACE pAllowedAce)
{
}
void ParseAce(PSYSTEM_ALARM_CALLBACK_OBJECT_ACE pAllowedAce)
{
}
void ParseAce(PSYSTEM_AUDIT_ACE pAllowedAce)
{
}
void ParseAce(PSYSTEM_MANDATORY_LABEL_ACE pAllowedAce)
{
}
void ParseAce(PACE_HEADER pAceHdr)
{
cout<<"-------------------------------------"<AceFlags);
cout<AceType == ACCESS_ALLOWED_ACE_TYPE)
{
cout<<"ACCESS_ALLOWED_ACE_TYPE"<AceType == ACCESS_DENIED_ACE_TYPE)
{
cout<<"ACCESS_DENIED_ACE_TYPE"<AceType == SYSTEM_ALARM_OBJECT_ACE_TYPE)
{
cout<<"SYSTEM_ALARM_OBJECT_ACE_TYPE"<AceType == SYSTEM_ALARM_ACE_TYPE)
{
cout<<"SYSTEM_ALARM_ACE_TYPE"<AceType == SYSTEM_ALARM_CALLBACK_ACE_TYPE)
{
cout<<"SYSTEM_ALARM_CALLBACK_ACE_TYPE"<AceType == SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE)
{
cout<<"SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE"<AceType == SYSTEM_AUDIT_ACE_TYPE)
{
cout<<"SYSTEM_AUDIT_ACE_TYPE"<AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE)
{
cout<<"SYSTEM_MANDATORY_LABEL_ACE_TYPE"<
3. 为新建对象使用安全描述符(或更改描述符)
#define MAKESDCDESC(sdc) {sdc, _T(#sdc)}
struct SdcDesc
{
DWORD sdc;
TCHAR* desc;
};
SdcDesc gvSdcDesc[]=
{
MAKESDCDESC(SE_DACL_AUTO_INHERIT_REQ),
MAKESDCDESC(SE_DACL_AUTO_INHERITED),
MAKESDCDESC(SE_DACL_DEFAULTED),
MAKESDCDESC(SE_DACL_PRESENT),
MAKESDCDESC(SE_DACL_PROTECTED),
MAKESDCDESC(SE_GROUP_DEFAULTED),
MAKESDCDESC(SE_OWNER_DEFAULTED),
MAKESDCDESC(SE_RM_CONTROL_VALID),
MAKESDCDESC(SE_SACL_AUTO_INHERIT_REQ),
MAKESDCDESC(SE_SACL_AUTO_INHERITED),
MAKESDCDESC(SE_SACL_DEFAULTED),
MAKESDCDESC(SE_SACL_PRESENT),
MAKESDCDESC(SE_SACL_PROTECTED),
MAKESDCDESC(SE_SELF_RELATIVE)
};
void dumpSdc(SECURITY_DESCRIPTOR_CONTROL controlBit)
{
USES_CONVERSION;
CString strDesc;
int count = sizeof(gvSdcDesc)/sizeof(SdcDesc);
for (int i=0;i
ps:判断当前用户是否域登录,可以先查询用户所属的组,再用LookupAccountSid查询组Sid的SID_NAME_USE