2009年6月25日 星期四

Duplicate User Token

-------December 13,2009

由于blog长期没有维护,之前那篇文章广告积累过多
再加上blogger的删除评论功能又很纠结。

故决定删除原文,重新发布此文

此次发布,未对文章内容进行修改
现在看来,之前这篇文章真的是没有什么效用
而且还有很多疏漏与不当之处
许多地方都很繁琐。

不过,作为我成长过程的一个记录,还是保留下来吧。
---------------------------

新本入手,Vista体验中...
体验过程中发现过去一直在使用的一段代码已经不奏效了。
既然如此,那么公开出来也无妨。
看来Agent Starter就要迎来又一次久违的大改了。
这回比较懒,我就不修改、注释了,也没有处理错误,有疑问,可留言。

功能:在当前进程为SYSTEM权限时,绕过密码登陆,获取当前已登录用户的Token。此Token可用于CreateProcessAsUser。

返回值:成功则是HANDLE,失败返回0.

Story:

在当前进程为SYSTEM权限时,由于CreateProcess等函数创建进程时父进程的权限会被子进程所继承,并且子进程也会登录为系统用户,容易造成子进程在获取用户设置时出错。目前已知CreateProcessAsUser和CreateProcessWithLogonW可以创建不同于父进程用户的子进程。但是由于CreateProcessAsUser所用的Token需要通过LogonUser 获得,而CreateProcessWithLogonW与LogonUser均需要用户名与密码才可进行登录,这使得获取Token失去了随意性。

这时,曾经在网上盛传的DuplicateHandle获取进程HANDLE法便可以用来解决问题。已知Token的ObjectNumber为4。所以我们便可以Duplicate其他进程里面的Token用于CreateProcessAsUser,从而免除登陆用户的麻烦。但是我们的Token要从哪里来呢?想想创建taskmgr.exe的是winlogon.exe,而winlogon.exe显示为SYSTEM用户,创建后的taskmgr则为当前用户。想必那里会隐藏着用户Token。打开Process Explorer看看,果真如此。至此,事情就变得简单了。(另外,winlogon里存在多个用户Token,XP SP3里面只有一个可用于我们的CreateProcessAsUser。Vista下没有可以直接用的。打算研究一下DuplicateTokenEx或许能有帮助)

代码:


HANDLE YGetUserToken()
{
      HANDLE ph,h_dup;
      ULONG bytesIO,i,NumOfHandle,WinLogon_id;
      PVOID buf;
      PSYSTEM_HANDLE_INFORMATION h_info;

      CHAR InfoBuffer[1000],szAccountName[200], szDomainName[200];

      DWORD dwInfoBufferSize,dwAccountSize = 200, dwDomainSize = 200;

      bytesIO=0x40000;
      buf = 0;

      WinLogon_id = NametoPid(L"winlogon.exe");
      ph = OpenProcess(PROCESS_DUP_HANDLE,0,WinLogon_id); //YDupHandle(WinLogon_id);

      NtAllocateVirtualMemory((HANDLE)-1, &buf, 0, &bytesIO, MEM_COMMIT, PAGE_READWRITE);

      NtQuerySystemInformation(SystemHandleInformation, buf, 0x40000, &bytesIO);
      NumOfHandle = *(PULONG)buf;
      h_info = ( PSYSTEM_HANDLE_INFORMATION )((ULONG)buf+4);
      int ai=0;

      for (i= 0 ; i<NumOfHandle; i++, h_info++)
      {
            if (h_info->ProcessId==WinLogon_id&&h_info->ObjectTypeNumber == 4)
            {
                  NtDuplicateObject(ph, (PHANDLE)h_info->Handle, (HANDLE)-1, &h_dup,TOKEN_ALL_ACCESS,0,0);
                  PTOKEN_USER pTokenUser = (PTOKEN_USER)InfoBuffer;
                  SID_NAME_USE snu;

                  GetTokenInformation(h_dup,TokenUser,InfoBuffer,1000, &dwInfoBufferSize);

                  LookupAccountSid(NULL, pTokenUser->User.Sid, szAccountName,&dwAccountSize,szDomainName, &dwDomainSize, &snu);

                  if(strcmp(szAccountName,"NT ATHORITY\\\)) //Vista:SYSTEM
                  {
                        printf(szAccountName);
                        if(CreateProcessAsUserW(h_dup,NULL,L"winlogon.exe",NULL,NULL,FALSE,CREATE_SUSPENDED,NULL,NULL,&startupInfo,&ProcessInfo))
                        {
                              TerminateProcess(ProcessInfo.hProcess,0);
                              NtClose(ProcessInfo.hProcess);
                              NtClose(ProcessInfo.hThread);
                              break;
                        }
                  }
                  NtClose(ProcessInfo.hProcess);
                  NtClose(ProcessInfo.hThread);
                  NtClose(h_dup);

                  h_dup=0;
            }
      }
      CreateProcess()
      NtClose(ph);
      bytesIO = 0;
      NtFreeVirtualMemory((HANDLE)-1, &buf, &bytesIO, MEM_RELEASE);
      return h_dup;
}

沒有留言:

張貼留言