首页
社区
课程
招聘
[讨论]真相是CreateProcessWithLogonW句柄泄漏!!!
发表于: 2013-7-30 10:11 17169

[讨论]真相是CreateProcessWithLogonW句柄泄漏!!!

2013-7-30 10:11
17169
while(true)
  {
    HANDLE hp=NULL;  
    PROCESS_INFORMATION pi;   
    STARTUPINFO si;
    ZeroMemory( &si, sizeof(si) );
    si.wShowWindow = SW_SHOW;   
    si.lpDesktop = NULL;  
    si.cb=sizeof(STARTUPINFO);
    si.dwFlags=STARTF_USESHOWWINDOW;
   
    ZeroMemory( &pi, sizeof(pi) );
    char pcName[MAX_COMPUTERNAME_LENGTH + 1]={};
    int nameSize=MAX_COMPUTERNAME_LENGTH + 1;
    ::GetComputerNameA((LPSTR)&pcName,(LPDWORD)&nameSize);
    BOOL abc;  
    abc=CreateProcessWithLogonW((LPCWSTR)L"abc",(LPCWSTR)&pcName,(LPCWSTR)L"1",LOGON_WITH_PROFILE,NULL,(LPWSTR)L"C:\\Users\\Administrator\\Desktop\\selfDestroy.exe",CREATE_DEFAULT_ERROR_MODE,NULL,NULL,&si,&pi);
    if(abc)
    {
      ::WaitForSingleObject(pi.hProcess,INFINITE);
      ::CloseHandle((HANDLE)(pi.hProcess));
      ::CloseHandle(pi.hThread);
      ::CloseHandle(si.hStdError);//这三个handle也释放了,结果还是句柄泄漏
      ::CloseHandle(si.hStdInput);
      ::CloseHandle(si.hStdOutput);

    }  

  }

以上代码黏贴到你的vs上试一试!请改掉用户名以及密码还有exe路径试一试!

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (52)
雪    币: 38
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
awesomeness!!!!
2013-7-30 10:13
0
雪    币: 38
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
我的是win7系统,64版本的。是的都试一试,任务管理器的性能里句柄数不断增加,内存使用有增无减。你的机子要是24小时开机,此程序要是24小时运行的话,电脑就会变慢,最后跑不动了。
2013-7-30 11:03
0
雪    币: 65
活跃值: (60)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
4
虽然看不懂楼主在表达什么,为了谁而表达,但是看起来好厉害的样子!!
2013-7-30 11:28
0
雪    币: 38
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
你在说什么 - -||| 我说的是句柄泄漏啊,谁试谁泄漏
2013-7-30 11:36
0
雪    币: 45
活跃值: (55)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
6
bdwdd(1467956605) 2013-7-25 15:05:57
查看前后消息用死循环24小时测试自己的函数,过了差不多一天后发现内存不足?我new的都有delete啊?怎么回事?

2013-07-30, 10:11:50   【讨论】真相是CreateProcessWithLogonW句柄泄漏!!!
2013-7-30 11:47
0
雪    币: 38
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
你居然贴出了q群里的对话
2013-7-30 11:52
0
雪    币: 70
活跃值: (88)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
8
Mark!!
2013-7-30 12:52
0
雪    币: 89
活跃值: (53)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
CreateProcessWithLogonW

有create  就没有相应的destroy吗
2013-7-30 12:58
0
雪    币: 38
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
waitForSigleObject就是等它结束了,没什么destroy。微软一天不修补这个我一天不用这个函数,创建一个进程居然隐藏了那么多句柄要人释放
2013-7-30 14:34
0
雪    币: 112
活跃值: (57)
能力值: ( LV12,RANK:200 )
在线值:
发帖
回帖
粉丝
11
msdn中有例子,你看看你用的和人家用的有啥不同?
有句柄泄漏,M$的人肯定有测试出来.
vs2008 msdn : ms-help://MS.VSCC.v90/MS.MSDNQTR.v90.en/dllproc/base/createprocesswithlogonw.htm
#define UNICODE
#define _WIN32_WINNT 0x0500

#include <windows.h>
#include <stdio.h>
#include <userenv.h>

void DisplayError(LPWSTR pszAPI)
{
    LPVOID lpvMessageBuffer;

    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | 
        FORMAT_MESSAGE_FROM_SYSTEM,
        NULL, GetLastError(), 
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 
        (LPWSTR)&lpvMessageBuffer, 0, NULL);

    //
    //... now display this string
    //
    wprintf(L"ERROR: API        = %s.\n", pszAPI);
    wprintf(L"       error code = %d.\n", GetLastError());
    wprintf(L"       message    = %s.\n", (LPWSTR)lpvMessageBuffer);

    //
    // Free the buffer allocated by the system
    //
    LocalFree(lpvMessageBuffer);

    ExitProcess(GetLastError());
}

void wmain(int argc, WCHAR *argv[])
{
    DWORD     dwSize;
    HANDLE    hToken;
    LPVOID    lpvEnv;
    PROCESS_INFORMATION pi = {0};
    STARTUPINFO         si = {0};
    WCHAR               szUserProfile[256] = L"";

    si.cb = sizeof(STARTUPINFO);
    
    if (argc != 4)
    {
        wprintf(L"Usage: %s [user@domain] [password] [cmd]", argv[0]);
        wprintf(L"\n\n");
        return;
    }

    //
    // TO DO: change NULL to '.' to use local account database
    //
    if (!LogonUser(argv[1], NULL, argv[2], LOGON32_LOGON_INTERACTIVE, 
            LOGON32_PROVIDER_DEFAULT, &hToken))
        DisplayError(L"LogonUser");

    if (!CreateEnvironmentBlock(&lpvEnv, hToken, TRUE))
        DisplayError(L"CreateEnvironmentBlock");

    dwSize = sizeof(szUserProfile)/sizeof(WCHAR);

    if (!GetUserProfileDirectory(hToken, szUserProfile, &dwSize))
        DisplayError(L"GetUserProfileDirectory");

    //
    // TO DO: change NULL to '.' to use local account database
    //
    if (!CreateProcessWithLogonW(argv[1], NULL, argv[2], 
            LOGON_WITH_PROFILE, NULL, argv[3], 
            CREATE_UNICODE_ENVIRONMENT, lpvEnv, szUserProfile, 
            &si, &pi))
        DisplayError(L"CreateProcessWithLogonW");

    if (!DestroyEnvironmentBlock(lpvEnv))
        DisplayError(L"DestroyEnvironmentBlock");

    CloseHandle(hToken);
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
}
2013-7-30 14:58
0
雪    币: 38
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
是,经过ms测过的都没问题。windows不存在句柄泄漏。
我的是死循环,它才执行了一次能看出什么
2013-7-30 15:08
0
雪    币: 112
活跃值: (57)
能力值: ( LV12,RANK:200 )
在线值:
发帖
回帖
粉丝
13
你咋看得句柄泄漏结果? 抓图上来.
2013-7-30 15:19
0
雪    币: 112
活跃值: (57)
能力值: ( LV12,RANK:200 )
在线值:
发帖
回帖
粉丝
14
MS的用法是执行了一次,你在外面包了一层死循环,将你看句柄泄漏的界面截图上来。我给你改一个没有句柄泄漏的.

你看句柄泄漏用的啥工具? 截个图贴上来.
2013-7-30 15:23
0
雪    币: 112
活跃值: (57)
能力值: ( LV12,RANK:200 )
在线值:
发帖
回帖
粉丝
15
你用任务管理器,怎么看到的是你的测试程序句柄数量不断增加的?
2013-7-30 15:25
0
雪    币: 38
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
任务管理器有个性能选项卡,里面可以看到句柄数猛增!只要执行了这个循环就会。。所以这个函数句柄泄漏,至少说这个函数不可以用在服务器进程上,会卡慢服务器。。
2013-7-30 15:26
0
雪    币: 112
活跃值: (57)
能力值: ( LV12,RANK:200 )
在线值:
发帖
回帖
粉丝
17
MS提供的Demo, 测试不可能是跑一遍就算了的. 白盒测试,黑盒测试.
长时间运行测试,人家都是搞过的.

你很喜欢用撞墙的表情啊~~

我知道您的测试(句柄泄漏)方法了, 我给您改一个句柄不泄漏的.
2013-7-30 15:28
0
雪    币: 38
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
反正我死循环用CreateProcessAsUser来创建那个进程,然后关掉各种句柄系统没问题,内存使用也正常,就是换了这个CreateProcessWithLogonW函数就不行了,系统句柄数几百几百地增加,内存使用也一直增加,最后结果只有一个,系统跑不动了!
2013-7-30 15:32
0
雪    币: 112
活跃值: (57)
能力值: ( LV12,RANK:200 )
在线值:
发帖
回帖
粉丝
19
CreateProcessWithLogonW  API那失败,  别人那也遇到过.
说是域用户才可以成功.

我这没有域用户, 实验做不下去了.
我的环境Win7X64Sp1.

你用本地账户可以 ? CreateProcessWithLogonW 不失败?
你给的那段代码, 在vs2008下编译通不过, 是你做实验的Demo么?

我将MS的例子编译过了, 但是到 CreateProcessWithLogonW 处会失败
ERROR: API        = CreateProcessWithLogonW.
       error code = 0x422.
       message    = 无法启动服务,原因可能是已被禁用或与其相关联的设备没有启动。


你能将你做实验的那个Demo工程, 在本地实验完了,传到主贴么?
// srcOK.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <windows.h>
#include <tchar.h>
#include <userenv.h>
#include <locale.h>

#pragma comment(lib, "Advapi32.lib")
#pragma comment(lib, "Userenv.lib")

#define G_LOGIN_NAME    L"administrator"
#define G_LOGIN_PWD     L"1"
#define G_PROG_NAME     L"C:\\windows\\system32\\notepad.exe"

void DisplayError(LPWSTR pszAPI)
{
    LPVOID lpvMessageBuffer;

    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | 
        FORMAT_MESSAGE_FROM_SYSTEM,
        NULL, GetLastError(), 
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 
        (LPWSTR)&lpvMessageBuffer, 0, NULL);

    //
    //... now display this string
    //
    wprintf(L"ERROR: API        = %s.\n", pszAPI);
    wprintf(L"       error code = 0x%X.\n", GetLastError());
    wprintf(L"       message    = %s.\n", (LPWSTR)lpvMessageBuffer);

    //
    // Free the buffer allocated by the system
    //
    LocalFree(lpvMessageBuffer);

    _tprintf(L"Error, press any key to quit");
    getwchar();

    ExitProcess(-1);
}

int _tmain(int argc, _TCHAR* argv[])
{
    BOOL    bIsLocalUser    =   TRUE;
    DWORD   dwSize          =   0;
    HANDLE  hToken          =   NULL;
    LPVOID  lpvEnv          =   NULL;

    PROCESS_INFORMATION pi = {0};
    STARTUPINFO         si = {0};
    WCHAR               szUserProfile[256] = {0};

    setlocale(LC_CTYPE, ".936");    //< 控制台为中文输出
    si.cb = sizeof(STARTUPINFO);

    //
    // TO DO: change NULL to '.' to use local account database
    //
    if (!LogonUser(	G_LOGIN_NAME, 
        NULL, 
        G_LOGIN_PWD,
        LOGON32_LOGON_INTERACTIVE, 
        LOGON32_PROVIDER_DEFAULT, 
        &hToken))
    {
        DisplayError(L"LogonUser");
    }

    if (!CreateEnvironmentBlock(&lpvEnv, hToken, TRUE))
        DisplayError(L"CreateEnvironmentBlock");

    dwSize = sizeof(szUserProfile)/sizeof(WCHAR);

    if (!GetUserProfileDirectory(hToken, szUserProfile, &dwSize))
        DisplayError(L"GetUserProfileDirectory");

    //
    // TO DO: change NULL to '.' to use local account database
    //

    /**
    ERROR: API        = CreateProcessWithLogonW.
    error code = 0x422.
    message    = 无法启动服务,原因可能是已被禁用或与其相关联的设备没有启动。
    */
    /// 必须要判断是否为本地用户, 否则会出现0x422的错误

    bIsLocalUser = (NULL != wcschr(G_LOGIN_NAME, L'@')) ? FALSE : TRUE;

    /// 参数2 用 L"." 和 NULL 都实验过了
    /// 好像用域用户才行, 本地用户不行
    /// 我这没域用户的环境...
    if (!CreateProcessWithLogonW(
            G_LOGIN_NAME, 
            NULL, // bIsLocalUser ? L"." : NULL, 
            G_LOGIN_PWD, 
            LOGON_WITH_PROFILE, 
            NULL, 
            G_PROG_NAME, 
            CREATE_UNICODE_ENVIRONMENT, 
            lpvEnv, 
            szUserProfile, 
            &si,
            &pi))
    {
        DisplayError(L"CreateProcessWithLogonW");
    }

    _tprintf(L"OK \r\n");
    if (!DestroyEnvironmentBlock(lpvEnv))
        DisplayError(L"DestroyEnvironmentBlock");

    CloseHandle(hToken);
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);

    getwchar();
    return 0;
}



你能将你做实验的那个Demo工程, 在本地实验完了,传到主贴么?
2013-7-30 17:43
0
雪    币: 112
活跃值: (57)
能力值: ( LV12,RANK:200 )
在线值:
发帖
回帖
粉丝
20
你的代码进 if(abc) 判断了么?? 你打句日志看下.
CreateProcessWithLogonW 用本地账户会执行失败的.
if(abc)
    {
      ::WaitForSingleObject(pi.hProcess,INFINITE);
      ::CloseHandle((HANDLE)(pi.hProcess));
      ::CloseHandle(pi.hThread);
      ::CloseHandle(si.hStdError);//这三个handle也释放了,结果还是句柄泄漏
      ::CloseHandle(si.hStdInput);
      ::CloseHandle(si.hStdOutput);

    }  



按照你的首帖上整理出来的工程, 原来是编译不过的.
你拿这个工程, 将用户名和口令改了,看在你那能运行么?
主要是看 CreateProcessWithLogonW 那是否执行成功

都按照你原先的来,只是整理.
整理后的能编译通过的工程 srcBad.rar

看你的代码,也不是域用户啊.
难道和Windows版本有关系?
上传的附件:
2013-7-30 17:47
0
雪    币: 38
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
判断了,单步都能跟进去

代码:

void CwhileCreatePDlg::OnBnClickedButton1()
{
        while(true)
        {
                HANDLE hp=NULL;       
                PROCESS_INFORMATION pi;   
                STARTUPINFO si;
                ZeroMemory( &si, sizeof(si) );
                si.wShowWindow = SW_SHOW;   
                si.lpDesktop = NULL;  
                si.cb=sizeof(STARTUPINFO);
                si.dwFlags=STARTF_USESHOWWINDOW;
               
                ZeroMemory( &pi, sizeof(pi) );
                char pcName[MAX_COMPUTERNAME_LENGTH + 1]={};
                int nameSize=MAX_COMPUTERNAME_LENGTH + 1;
                ::GetComputerNameA((LPSTR)&pcName,(LPDWORD)&nameSize);
                BOOL abc;       
                abc=CreateProcessWithLogonW((LPCWSTR)L"abc",(LPCWSTR)&pcName,(LPCWSTR)L"1",LOGON_WITH_PROFILE,NULL,(LPWSTR)L"C:\\Users\\Administrator\\Desktop\\selfDestroy.exe",CREATE_DEFAULT_ERROR_MODE,NULL,NULL,&si,&pi);
                if(abc)
                {
                        ::WaitForSingleObject(pi.hProcess,INFINITE);
                        ::CloseHandle((HANDLE)(pi.hProcess));
                        ::CloseHandle(pi.hThread);
                        ::CloseHandle(si.hStdError);
                        ::CloseHandle(si.hStdInput);
                        ::CloseHandle(si.hStdOutput);

                }       

        }
}
2013-7-30 18:01
0
雪    币: 112
活跃值: (57)
能力值: ( LV12,RANK:200 )
在线值:
发帖
回帖
粉丝
22
你在我贴的那个工程上, srcBad.rar 那个工程在20楼的尾部, 试试, 是否能成功。
如果不成功,将那个工程改成能运行的.
将该改完的工程再传上来.
我这现在因为那个函数执行失败,没发再实验了。

你那的Windows是什么? winXp? Win7X64?
2013-7-30 18:05
0
雪    币: 4343
活跃值: (4328)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
那是肯定会增加句柄的好不?    又不是函数本身的问题 而是因为你创建的进程需要创建句柄. 比如新进程窗口和进程,及线程     多开一个进程,句柄就多出一部分.
2013-7-30 18:40
0
雪    币: 112
活跃值: (57)
能力值: ( LV12,RANK:200 )
在线值:
发帖
回帖
粉丝
24
他的用法是守护进程
开一份进程,如果进程被结束了,关掉改观的句柄, 再开新的一份进程.
句柄数量不该持续增长.
2013-7-30 18:59
0
雪    币: 2676
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
Win7 64位系统,没有发现泄漏。CreateProcessWithLogonW函数执行完后,只多出来对应进程和线程的两个句柄,关闭这两个后,句柄数恢复原值。
只有第一次执行CreateProcessWithLogonW后,会多出一些与logon和WindowStation相关的一些句柄,但这些句柄基本稳定,第二次和以后的CreateProcessWithLogonW执行,句柄数就如上所说的了。

建议不要看整个系统的句柄数,而应该看这个指定进程的句柄数。同时,尽量关闭杀毒软件等会对系统hook的程序,再重新测试,可能是第三方软件泄漏了。
2013-7-30 20:28
0
游客
登录 | 注册 方可回帖
返回
//