Ich bin HackPascal

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

    以前一直以为启动一个 SYSTEM 权限的进程是件很麻烦的事,查资料发现在 XP 及 2003 下可以通过获取 winlogon.exe 的令牌来启动 SYSTEM 权限的进程,而这招在 Windows 7 下却行不通了。因此唯一的方法就是在服务里启动进程,但 Windows 7 又存在 Session 0 隔离机制,无法直接访问创建的进程,这让我感到很困惑。

    后来发现 MSDN 上有篇文章(http://msdn.microsoft.com/en-us/library/windows/desktop/aa379608(v=vs.85).aspx),它允许在服务中以指定的身份启动一个交互式进程,但是我看了半天都没发现怎么才能以 SYSTEM 权限启动。。。。。。。。。直到偶然间看到了一个 API SetTokenInformation,我才发现原来要启动一个 SYSTEM 权限的进程是如此的简单。。。

    主要思路是:首先保证服务是运行在 SYSTEM 权限下的,然后获取自身的进程令牌,接着设置令牌的 Session 信息,最后用 CreateProcessAsUser 启动就行了。

function WTSGetActiveConsoleSessionId(): THandle; stdcall; external 'kernel32.dll';

function CreateSystemProcess(lpCommandLine: String): BOOL;
var
  hToken, hDuplicatedToken: THandle;
  dwSessionId: DWORD;
  si: STARTUPINFO;
  pi: PROCESS_INFORMATION;
begin
  //打开自身进程令牌
  if OpenProcessToken(GetCurrentProcess,TOKEN_ALL_ACCESS,hToken) then
  begin
    //将令牌复制一份,成为主令牌,以保证能够用来启动进程
    if DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, nil, SecurityIdentification, TokenPrimary, hDuplicatedToken) then
    begin
      CloseHandle(hToken);
      hToken := hDuplicatedToken;
      //获取当前活动的 Session
      dwSessionId := WTSGetActiveConsoleSessionId;
      //设置令牌的 Session 为活动的 Session
      if SetTokenInformation(hToken, TokenSessionId, @dwSessionId, SizeOf(DWORD)) then
      begin
        ZeroMemory(@si, SizeOf(si));
        si.cb := SizeOf(si);
        si.lpDesktop := 'winsta0\default';
        si.wShowWindow := SW_SHOWNORMAL;
        //创建进程
        Result := CreateProcessAsUser(hToken, PChar(lpCommandLine), nil, nil, nil, True, 0, nil, nil, si, pi);
      end
      else
        Result := False;
    end
    else
      Result := False;
  end
  else
    Result := False;
  CloseHandle(hToken);
end;
posted on 2012-10-11 11:44  hackpascal  阅读(1858)  评论(4编辑  收藏  举报