menu

北方天空下

i am not a man of too many faces,the mask i wear is one...

Avatar

UAC提升权限的细节

在看UAC相关的东西时,发现对其内部逻辑还是不了解,为了方便后续的工作得将其搞懂,今天一整天查阅了一些资料后,大概搞懂了其中了逻辑,还是挺复杂的,这里备忘一下:
一,桌面运行一个程序时,Explorer调用ShellExecuteEx(),ShellExecuteEx()进一步调用CreateProcess()创建进程,由于这个进程需要管理员权限才能运行,于是CreateProcess返回ERROR_ELEVATION_REQUIRED (740)
二,ShellExecuteEx接到这个返回值后和一个运行appinfo服务的svchost通讯,要求它来进行权限提升,于是这个svchost创建consent.exe,consent正是UAC对话框的UI进程
三,如果用户在UAC对话框上选择允许,consent将这个结果返回给appinfo(svchost)后便退出,appinfo依据返回结果进行一系列的函数调用创建高权限进程:
1. appinfo首先获取到当前登录用户的高权限令牌;
2.appinfo初始化一个STARTUPINFOEX结构体:

typedef struct _STARTUPINFOEX {
  STARTUPINFO                 StartupInfo;
  PPROC_THREAD_ATTRIBUTE_LIST lpAttributeList;
}STARTUPINFOEX, *LPSTARTUPINFOEX;


期中:
A.初始化Startupinfo的时候将其成员lpDesktop设置为winsta0\default,使得将来创建的提升进程处于当前用户桌面上(否则就会在appinfo服务的这个不可见桌面上);
B.初始化lpAttributeList的时候会用OpenProcess()取得原始调用进程的进程句柄,然后调用UpdateProcThreadAttribute(),指定参数分别为:这个句柄和PROC_THREAD_ATTRIBUTE_PARENT_PROCESS,这一步后,将来创建的被提升进程的父进程就被还原为原始的调用进程的(否则他的父进程就会是Svchost(appinfo))
3. 接下来svchost(appinfo服务)调用CreateProcessAsUser()创建提升权限的进程:期中的参数设置是:
A.dwCreationFlags使用EXTENDED_STARTUPINFO_PRESENT(这个仅vista才有,用于指定倒数第二个参数lpStartupInfo指向的是STARTUPINFOEX而不是STARTUPINFO)
B.倒数第二个参数lpStartupInfo使用上述几步中初始化完成的结构体STARTUPINFOEX
4. 最后appinfo将相关函数调用返回给Explorer,一个提升权限的的进程被创建了,上述几步的设置使得这个由服务创建的进程运行在当前用户桌面、并且我们看到的它的父进程“依然是”Explorer。

参考资料:
http://www.codeproject.com/KB/vista-security/UAC__The_Definitive_Guide.aspx?msg=2281654
http://technet.microsoft.com/en-us/magazine/2007.06.uac.aspx
http://channel9.msdn.com/shows/Going+Deep/UAC-What-How-Why/

学习了!

1. appinfo首先获取到当前登录用户的高权限令牌;
''是怎么实现的

比如,我的程序是个服务,用户在SESSION 1中,我用他的explorer.exe的token创建的进程,权限是不够的。我想知道如何取到session1用户高权限token??

@匿名人士 据我所知好像没有一个现成的API做这个事情,因为session1用户的用于权限提升的“高级token”是在用户登陆的时候创建的并有系统保留的。如果你仅仅是因为权限不够,为什么不用你的服务程序的token呢,权限肯定是够的,如果你觉得桌面上面需要交互,那么就:
1.DuplicateToken服务的token,
2.把服务token的SessionID换为User的SessionID(自己实现函数,SetTokenInformation)
3.把GreateProcessAsUser的参数STARTUPINFO里的lpDesktop指定为winsta0\default
3.然后GreateProcessAsUser创建进程,其中要注意dwCreationFlags参数的使用,好像有一些特殊的地方。

评论已关闭