Windows系统巨涌很完善的安全和认证机制,称作访问控制机制。程序的执行主体线程在访问对象(文件、事件等)时,系统会根据线程的权限和线程需要访问的对象所具有的访问控制列表ACL中的“安全描述符”是否匹配来进行认证,决定一个线程是否可以操作一个对象。
基本概念:
A需要访问B,A就是访问的主体,B就是访问的客体。A的“访问令牌”和B的安全描述符共同决定了A是否可以访问B。
访问的主体是线程。在系统中,线程才是程序执行的流程,因此只有线程才能操作对象。每个线程都是属于一个进程的,线程并没有属于自己的权限,而是来源于线程所属于的进程。一个进程的所有线程都具有相同的权限,可以把进程看做访问的主体。一个线程能访问哪些对象,能进行哪些操作,是由线程权限决定的。
访问的客体是安全对象,所有被访问的对象都具有安全描述符,包括了文件、注册表、事件、互斥、管道等。
访问令牌、权限和用户标识
进程的权限继承自创建进程的用户和用户所属的用户组。用户有专用数据结构来表示权限(访问令牌)。访问令牌包括两个部分:一个是令牌所表示的用户,包括用户标识符(SID),用户所属的用户组等;另一部分是“权限”(Privilege)。
在进程访问安全对象是,会用到SID。每个安全对象都有访问控制列表ACL,ACL说明了哪些用户SID能访问本对象,哪些不能,以及能进行哪种访问等。而“权限”在访问摸个具体的安全对象是并没有作用,“权限”是表示进程是否能够进行特定的系统操作,如关闭系统、修改系统时间、加载设备驱动等。
创建进程的API函数时CreateProcess,CreateProcess函数所创建的进程使用的访问令牌是当前登录用户的访问令牌。此外还可以指定进程的用户。使用CreateProcessAsUser和CreateProcessWithTokenW等API函数,在创建前需要先得到用户的令牌,可以使用LogonUser登录用户,logonUser函数返回用户的令牌。
如果需要得到进程和线程的访问令牌,可以使用OpenProcessToken、OpenThreadToken等函数。获取令牌中的信息可以使用API函数GetTokenInfomation。如果需要修改“权限”,可以使用AdjustTokenPrivileges等函数。
进程的系统操作权限:
进程的权限特指进程是否能够进行各种系统操作,例如是否可以关闭系统,是否能够修改系统时间,是否能够加载设备驱动等。权限是一个列表,每种权限是列表中的一项。权限列表存在于进程的访问令牌中。
权限有很多种,每一种表示了一个特定的操作是否能够进行,如果进程的访问令牌中的权限列表中有这个权限,则表示进程可以进行这种操作,比如SE_LOAD_DRIVER_NAME表示进程可以加载驱动。
安全对象:
Windows系统几乎所有的对象都有安全属性,包括文件、文件夹、注册表、线程同步对象、进程间通信对象、网络共享等,进程和线程也可以是其他进程的操作对象,所以进程和线程也是安全对象。
在创建对象是都可以指定对象的安全属性,比如CreateFile、CreatePipe、CreateProcess、RegCreateKeyEx和RegSaveKeyEx等。SECURITY_ATTRIBUTES结构用于指定对象的安全属性。
GetNamedSecurityInfo、GetSecurityInfo、SetSecurityInfo、SetKenelObjectSecurity、SetNameSecurityInfo等API函数可以获取和设置对象的安全属性。
对象的安全属性石以安全描述符(Security Descriptor)形式存在的,安全描述符中包括了访问控制列表。
访问控制列表ACL:
每个安全对象都有访问控制列表。访问控制列表有两种,一种是选择访问控制列表(DACL=Discretionary Access Control List),另一种是系统访问控制列表(SACL=System Access Control List)。DACL决定了用户或用户组是否能访问这个对象,SACL控制了尝试访问安全对象的检测信息的继承关系。
DACL是访问控制的关键。DACL中包括了一个访问控制入口(ACE=Access Control Entries)列表。ACE表明了用户(通过用户SID或用户组SID)是否能够进行操作以及能进行哪种操作。在进行访问控制检测是,会一次检测DACL中的ACE,直到被允许或被拒绝。
OpenProcessToken 获取进程的Token句柄。
OpenThreadToken 获取线程的Token句柄。
LookupPrivilegeValue 通过权限名获取LUID。
AdjustTokenPrivileges 调整令牌的权限。
GetTokenInformation 从Token中获取信息。
LookupAccountSid 以SID作为输入获取获取SID的用户名和所在的域名。
LookupAccountName 以用户名或系统名作为输入获取SID。
GetFileSecurity 获取文件的安全信息和权限。
SetFileSecurity 设置文件的安全属性。
GetSecurityDescriptorDac
l 从安全描述符中获取DACL。
GetAce 从DACL中获取指定索引的ACE。
IsValidAce 判断ACL是否有效。
GetAclInfomation 获取ACL信息。
SetSecurityDescriptorDac
l 设置DACL信息。
用户
NetUserAdd 创建用户。
NetUserDel 删除用户。
NetGroupAddUser 将用户添加到用户组。
NetGroupDelUser 从用户组中删除用户。
NetGroupAdd 增加用户组。
NetGroupDel 删除用户组。
NetUserEnum 列举指定主机中当前的所有用户。
NetLocalGroupEnum 列举指定主机中当前的所有用户组。
NetUserGetInfo 获取指定主机指定用户名的用户信息。