c+o+m and u+a+c Notes

 参考网站为:

http://blog.csdn.net/woshisadshiwo/article/details/6853564 

http://blog.csdn.net/woshinia/article/details/7850295

http://blog.csdn.net/xieqidong/article/details/2936771

 

1. com相关

使用atl的com 选择服务器类型的,工程为vs2008 ,com service相关命令 demoname.exe /Service , net start demoname,net stop  demoname,demoname.exe /UnRegServer

在class CNoUacComModule : public CAtlServiceModuleT< CNoUacComModule, IDS_SERVICENAME >下面添加下列代码

//修改服务的进程安全设置

HRESULT InitializeSecurity() throw()
 {
  // TODO : 调用 CoInitializeSecurity 并为服务提供适当的
  // 安全设置
  // 建议 - PKT 级别的身份验证、
  // RPC_C_IMP_LEVEL_IDENTIFY 的模拟级别
  // 以及适当的非 NULL 安全说明符。
  return CoInitializeSecurity( NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_NONE,
   RPC_C_IMP_LEVEL_IDENTIFY, NULL, EOAC_NONE, NULL );
  //return S_OK;
 }

//修改服务的描述

HRESULT RegisterAppId(bool bService = false)
 {
  OutputDebugStringA("============= RegisterAppId ============================================== \n");
  HRESULT hr = S_OK;
  BOOL res = __super::RegisterAppId(bService);
  if (bService)
  {
   if (IsInstalled())
   {
    OutputDebugString(m_szServiceName);
    SC_HANDLE hSCM = ::OpenSCManagerW(NULL, NULL, SERVICE_CHANGE_CONFIG);
    SC_HANDLE hService = NULL;
    if (hSCM == NULL)
     hr = AtlHresultFromLastError();
    else

  {
     hService = ::OpenService(hSCM, m_szServiceName, SERVICE_CHANGE_CONFIG);
     if (hService != NULL)
     {
      ::ChangeServiceConfig(hService, SERVICE_NO_CHANGE,
           SERVICE_AUTO_START,//修改服务为 自动启动
           NULL, NULL, NULL, NULL, NULL, NULL, NULL,
           m_szServiceName); // 通过修改资源IDS_SERVICENAME 修改服务的显示名字

      SERVICE_DESCRIPTION Description;
      TCHAR szDescription[1024];
      ZeroMemory(szDescription, 1024);
      ZeroMemory(&Description, sizeof(SERVICE_DESCRIPTION));
      lstrcpy(szDescription, _T("示例服务,by nanjun@ligsoft.com"));

      Description.lpDescription = szDescription;
      ::ChangeServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION, &Description);
      ::CloseServiceHandle(hService);
     }
     else
      hr = AtlHresultFromLastError();
     ::CloseServiceHandle(hSCM);
    }
   }
  }
  return hr;
 }

 

HRESULT PreMessageLoop(int nShowCmd) throw()
 {
  HRESULT hr = __super::PreMessageLoop(nShowCmd);
  // 微软的BUG
  if (hr == S_FALSE)
   hr = S_OK;
  if (SUCCEEDED(hr))
  {
   // Add any custom code to initialize your service
   // 这个状态一定要修改,否则会出现1053错误,
   // 这个错误我花了很多时间才搞定
   SetServiceStatus(SERVICE_RUNNING);
  }
  return hr;
 }

HRESULT PostMessageLoop() throw()
 {
  HRESULT hr = __super::PostMessageLoop();

  if (SUCCEEDED(hr))
  {
   // Add any custom code to uninitialize your service
  }
  return hr;
 }

 void OnStop() throw()
 {
  __super::OnStop();
  SetServiceStatus(SERVICE_STOPPED);
 }

 void OnPause() throw()
 {
  __super::OnPause();
  SetServiceStatus(SERVICE_PAUSED);
 }

 void OnContinue() throw()
 {
  __super::OnContinue();
  SetServiceStatus(SERVICE_RUNNING);
 }

接下来切换到类属性 选择添加类(CAuthorityControl) 选择atl简单对象,添加好了之后 ,

在对应的IAuthorityControl添加函数(一定要在IAuthorityControl不要在CAuthorityControl),这样就可以供给调用方去调用了。

修改reg文件 例如:AuthorityControl.rgs

原来的为:

HKCR
{
 NoUacCom.AuthorityControl.1 = s 'AuthorityControl Class'
 {
  CLSID = s '{9E723EF4-5251-42D4-BF8B-E2D4C9613B9A}'
 }
 NoUacCom.AuthorityControl = s 'AuthorityControl Class'
 {
  CLSID = s '{9E723EF4-5251-42D4-BF8B-E2D4C9613B9A}'
  CurVer = s 'NoUacCom.AuthorityControl.1'
 }
 NoRemove CLSID
 {
  ForceRemove {9E723EF4-5251-42D4-BF8B-E2D4C9613B9A} = s 'AuthorityControl Class'
  {
   ProgID = s 'NoUacCom.AuthorityControl.1'
   VersionIndependentProgID = s 'NoUacCom.AuthorityControl'
   ForceRemove 'Programmable'
   LocalServer32 = s '%MODULE%'
   'TypeLib' = s '{072E3124-EA52-4903-AF11-B080578F1197}'
  }
 }
}

修改为:

HKCR
{
 NoUacCom.AuthorityControl.1 = s 'NoUacCom'
 {
  CLSID = s '{9E723EF4-5251-42D4-BF8B-E2D4C9613B9A}'
 }
 NoUacCom.AuthorityControl = s 'NoUacCom'
 {
  CLSID = s '{9E723EF4-5251-42D4-BF8B-E2D4C9613B9A}'
  CurVer = s 'NoUacCom.AuthorityControl.1'
 }
 NoRemove CLSID

{
  ForceRemove {9E723EF4-5251-42D4-BF8B-E2D4C9613B9A} = s 'NoUacCom' //这个一定要和应用程序的名称一致
  {
   ProgID = s 'NoUacCom.AuthorityControl.1'
   VersionIndependentProgID = s 'NoUacCom.AuthorityControl'
   ForceRemove 'Programmable'
   LocalServer32 = s '%MODULE%'
   val AppID = s '%APPID%' //第一要用appid
   'TypeLib' = s '{072E3124-EA52-4903-AF11-B080578F1197}'
  }
 }
}

HKCR 修改为上面的就可以不用启动服务了net start "service name"  只需要安装服务demoname.exe /Service 即可。

 

2.躲过uac

躲过uac需要服务的帮助,也就是需要上面的com service 下面是实现代码

STDMETHODIMP CAuthorityControl::LaunchAppIntoDifferentSession(BSTR filePath, LONG* ret)

{

   ///在服务中用管理员权限创建一个可弹出UI的进程 (这个是可以弹出窗口的) 并且可以绕过uac

   HANDLE hToken = NULL;  

   HANDLE hTokenDup = NULL;  

   BOOL bSuccess = TRUE;

    do   

    {  

        if(OpenProcessToken(GetCurrentProcess(),TOKEN_ALL_ACCESS,&hToken))  

        {  

            if(DuplicateTokenEx(hToken, TOKEN_ALL_ACCESS,NULL, SecurityIdentification, TokenPrimary, &hTokenDup))  

            {  

                DWORD dwSessionId = WTSGetActiveConsoleSessionId();  

                if(!SetTokenInformation(hTokenDup,TokenSessionId,&dwSessionId,sizeof(DWORD)))  

                {  

                    printf("SetTokenInformation error !error code:%d\n",GetLastError());

                    bSuccess = FALSE;  

                    break;  

                }  

  

                STARTUPINFO si;  

                PROCESS_INFORMATION pi;  

                ZeroMemory(&si,sizeof(STARTUPINFO));  

                ZeroMemory(&pi,sizeof(PROCESS_INFORMATION));  

                si.cb = sizeof(STARTUPINFO);  

                si.lpDesktop = _T("WinSta0\\Default");  

                si.wShowWindow = SW_SHOW;  

                si.dwFlags     =   STARTF_USESHOWWINDOW /*|STARTF_USESTDHANDLES*/;  

  

                LPVOID pEnv = NULL;  

                DWORD dwCreationFlag = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT;  

                if(!CreateEnvironmentBlock(&pEnv,hTokenDup,FALSE))  

                {  

                    printf("CreateEnvironmentBlock error !error code:%d\n",GetLastError());

                    bSuccess = FALSE;  

                    break;  

                }  

                LPCWSTR szfilePath = static_cast<LPCWSTR>(filePath);

                if(!CreateProcessAsUser(hTokenDup,szfilePath,NULL,NULL,NULL,FALSE,dwCreationFlag,pEnv,NULL,&si,&pi))  

                {  

                    printf("CreateProcessAsUser error !error code:%d\n",GetLastError());

                    bSuccess = FALSE;  

                    break;  

                }  

  

                if(pEnv)  

                {  

                    DestroyEnvironmentBlock(pEnv);  

                }  

            }  

            else  

            {  

               printf("DuplicateTokenEx error !error code:%d\n",GetLastError());

                bSuccess = FALSE;  

                break;  

            }  

  

                  

        }  

        else  

        {  

            printf("cannot get administror!error code:%d\n",GetLastError());

            bSuccess = FALSE;  

            break;  

        }  

    }while(0);  

  

    if(hTokenDup != NULL && hTokenDup != INVALID_HANDLE_VALUE)  

        CloseHandle(hTokenDup);  

   if(hToken != NULL && hToken != INVALID_HANDLE_VALUE)  

        CloseHandle(hToken);  

if (bSuccess)
 {
  *ret = 0;
 }
 else
 {
  *ret = 1;
 }

}

还有一种方式也可以躲过uac    但是不能弹出ui

  PROCESS_INFORMATION pi;
   STARTUPINFO si;
   BOOL bResult = FALSE;
   DWORD dwSessionId,winlogonPid;
   HANDLE hUserToken,hUserTokenDup,hPToken,hProcess;
   DWORD dwCreationFlags;

   dwSessionId = WTSGetActiveConsoleSessionId();

//
   //查找winlogon进程

   PROCESSENTRY32 procEntry;

    HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (hSnap == INVALID_HANDLE_VALUE)
    {
        return 1 ;
    }

    procEntry.dwSize = sizeof(PROCESSENTRY32);

    if (!Process32First(hSnap, &procEntry))
    {
        return 1 ;
    }

    do
    {
        if (_stricmp(procEntry.szExeFile, "winlogon.exe") == 0)
        {
        //找到winlogon进程
        //确定它运行在控制台会话中
            DWORD winlogonSessId = 0;
            if (ProcessIdToSessionId(procEntry.th32ProcessID, &winlogonSessId)
                    && winlogonSessId == dwSessionId)
            {
                winlogonPid = procEntry.th32ProcessID;
                break;
            }
        }

    } while (Process32Next(hSnap, &procEntry));

   WTSQueryUserToken(dwSessionId,&hUserToken);
   dwCreationFlags = NORMAL_PRIORITY_CLASS|CREATE_NEW_CONSOLE;
   ZeroMemory(&si, sizeof(STARTUPINFO));
   si.cb= sizeof(STARTUPINFO);
   si.lpDesktop = "winsta0//default";
   ZeroMemory(&pi, sizeof(pi));
   TOKEN_PRIVILEGES tp;
   LUID luid;
   hProcess = OpenProcess(MAXIMUM_ALLOWED,FALSE,winlogonPid);

   if(!::OpenProcessToken(hProcess,TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY
                 |TOKEN_DUPLICATE|TOKEN_ASSIGN_PRIMARY|TOKEN_ADJUST_SESSIONID
                          |TOKEN_READ|TOKEN_WRITE,&hPToken))
   {
               int abcd = GetLastError();
               printf("Process token open Error: %u/n",GetLastError());
   }

   if (!LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&luid))
   {
       printf("Lookup Privilege value Error: %u/n",GetLastError());
   }
   tp.PrivilegeCount =1;
   tp.Privileges[0].Luid =luid;
   tp.Privileges[0].Attributes =SE_PRIVILEGE_ENABLED;

   DuplicateTokenEx(hPToken,MAXIMUM_ALLOWED,NULL,
            SecurityIdentification,TokenPrimary,&hUserTokenDup);
   int dup = GetLastError();

   //调整令牌权限
   SetTokenInformation(hUserTokenDup,
        TokenSessionId,(void*)dwSessionId,sizeof(DWORD));

   if (!AdjustTokenPrivileges(hUserTokenDup,FALSE,&tp,sizeof(TOKEN_PRIVILEGES),
                        (PTOKEN_PRIVILEGES)NULL,NULL))
   {
       int abc =GetLastError();
       printf("Adjust Privilege value Error: %u/n",GetLastError());
   }

   if (GetLastError()== ERROR_NOT_ALL_ASSIGNED)
   {
     printf("Token does not have the provilege/n");
   }

   LPVOID pEnv =NULL;

   if(CreateEnvironmentBlock(&pEnv,hUserTokenDup,TRUE))
   {
       dwCreationFlags|=CREATE_UNICODE_ENVIRONMENT;
   }
   else
      pEnv=NULL;

//在用户登录的会话中启动进程

  bResult = CreateProcessAsUser(
      hUserTokenDup,                  //用户的访问令牌
      _T("C://SessionLauncher//a.exe"),   //要执行的文件
      NULL,                          //命令行
      NULL,                          //进程指针SECURITY_ATTRIBUTES
      NULL,                          //线程指针SECURITY_ATTRIBUTES
      FALSE,                         //句柄不可继承
      dwCreationFlags,                //创建标志
      pEnv,                          //指向新环境块的指针
      NULL,                         //当前目录名
      &si,                           //指向STARTUPINFO结构的指针
      &pi                           //新进程的相关信息
   );

   int iResultOfCreateProcessAsUser = GetLastError();//此处结果应为0

//关闭所有句柄

  CloseHandle(hProcess);
  CloseHandle(hUserToken);
  CloseHandle(hUserTokenDup);
  CloseHandle(hPToken);

 return 0;
}

3.测试我们的com

在测试程序里面添加引用或者是把 上面的com工程中的生成文件copy到 测试工程中

#include "..\NoUacCom\NoUacCom_i.h"
#include "..\NoUacCom\NoUacCom_i.c"

 

IAuthorityControl * pIAuthorit=NULL;  // 我们定义的接口
 // 初始化
 HRESULT hr = CoInitialize(NULL);
 if(FAILED(hr))
 {
  printf("Coinitialize failed! hr=0x%x", hr);
  system("pause");
  return 0;
 }

 // 创建COM对象
 hr = CoCreateInstance(CLSID_AuthorityControl, NULL, CLSCTX_ALL,
  IID_IAuthorityControl, (void **)&pIAuthorit);
 if(FAILED(hr))
 {
  printf("create com failed! hr=0x%x", hr);
  CoUninitialize();
  system("pause");
  return 0;
 }

BSTR bstr = NULL;

 bstr = SysAllocString ( runExePath.c_str() );
 if ( NULL == bstr )
 {
  printf("SysAllocString out of memory error \r\n");
 }
 else
 {
  hr = pIAuthorit->LaunchAppIntoDifferentSession(bstr,&ret);
  SysFreeString (bstr);
  if(FAILED(hr))
  {
   printf("pIAuthorit->testFun() failed! hr=0x%x", hr);
   pIAuthorit->Release();
   CoUninitialize();
   system("pause");
   return 0;
  }
 }

 

4.下面说一下怎么测试 服务

第一种就是输出到日志文件中。

第二种就是先安装了服务,打了断点  在vs2008的  调试菜单选择 附加到进程,选择到你的进程(显示所有进程)这样就可以直接调试了  需要debug版本编译的服务

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值