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

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

2013-7-30 10:11
17182
收藏
免费 0
支持
分享
最新回复 (52)
雪    币: 155
活跃值: (20)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
26
我也怀疑是第三方泄露了,比如第三方驱动、包括第三方服务(因为这个函数需要和系统的Secondary Logon服务去交互(包括交换句柄))

CreateProcessWithLogonW这个函数已经出过一次WindowStation Handle的leak,不过那是在2000年,发生在windwos 2000 sp3上,sp4已经修复了

所以MS对这个case应该已经注意到了,按理说win7上再出泄露不太可能。
2013-7-31 07:23
0
雪    币: 993
活跃值: (442)
能力值: ( LV12,RANK:403 )
在线值:
发帖
回帖
粉丝
27
没看明白,CreateProcessWithLogonW 第二个参数明明要求LPCWSTR,上面却用GetComputerNameA((LPSTR)&pcName,(LPDWORD)&nameSize);
来取ANSI的计算机名,下面又强制转为(LPCWSTR)&pcName,为什么不定义成WCHAR pcName[MAX_COMPUTERNAME_LENGTH + 1]然后用
GetComputerNameW来取计算机名呢?这样强制转换就算不出错也是严重的逻辑错误,还有si结构体中的三个handle(hStdError、hStdInput、hStdOutput)是做为参数送进去做重定向的,前面赋值都没有赋值,后面CloseHandle哪门子的句柄呢?还是先好好看看各个API的说明再来说别人句柄泄不泄漏吧。
使用LOGON_WITH_PROFILE参数时,微软的说明如下:
Log on, then load the user profile in the HKEY_USERS registry key. The function returns after the profile is loaded. Loading the profile can be time-consuming, so it is best to use this value only if you must access the information in the HKEY_CURRENT_USER registry key.
Windows Server 2003:  The profile is unloaded after the new process is terminated, whether or not it has created child processes.
Windows XP:  The profile is unloaded after the new process and all child processes it has created are terminated.
There is a limit to the number of child processes that can be created by this function and run simultaneously. For example, on Windows XP, this limit is MAXIMUM_WAIT_OBJECTS*4. However, you may not be able to create this many processes due to system-wide quota limits.
2013-7-31 09:13
0
雪    币: 220
活跃值: (117)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
28
用xuetr看下句柄表.到底是什么类型的句柄泄漏的
2013-7-31 09:35
0
雪    币: 38
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
29
我的是Administrator创建普通的账户abc,你新建一个普通的账户试试看看。反正我使用CreateProcessAsUser没问题一使用这个CreateProcessWithLogonW就有问题,很大可能性是微软的问题
2013-7-31 10:30
0
雪    币: 38
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
30
进程都创建成功了,那个什么profile参数换成NULL结果还是一样泄漏,si里的三个句柄有则关闭,无则加勉,失败了也不影响什么
2013-7-31 10:32
0
雪    币: 38
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
31
好像坑爹的win7 64bit跑不了xuetr啊?
2013-7-31 10:33
0
雪    币: 38
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
32
单看进程句柄是没有什么异常,但是系统句柄猛增能使用嘛。。
2013-7-31 10:35
0
雪    币: 38
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
33
你把你的计算机名字填在那函数的第二个参数试试。
2013-7-31 10:38
0
雪    币: 993
活跃值: (442)
能力值: ( LV12,RANK:403 )
在线值:
发帖
回帖
粉丝
34
请看25楼那位兄弟的回复,再看看这个:
Windows Server 2003:  The profile is unloaded after the new process is terminated, whether or not it has created child processes.
Windows XP:  The profile is unloaded after the new process and all child processes it has created are terminated.
There is a limit to the number of child processes that can be created by this function and run simultaneously. For example, on Windows XP, this limit is MAXIMUM_WAIT_OBJECTS*4. However, you may not be able to create this many processes due to system-wide quota limits.
另外建议先把你的程序改好,句柄有则关闭,无则加勉,看起来没什么关系,最多就是多写句话,但是在程序逻辑里不该有的就是不能有,这种习惯即让你自己将来理解起来困难,别人看你的代码也会莫名其妙。
2013-7-31 10:39
0
雪    币: 993
活跃值: (442)
能力值: ( LV12,RANK:403 )
在线值:
发帖
回帖
粉丝
35
如果我没记错的话,xuetr作者出了新版本,改名叫PCHunter,对应64位的版本PCHunter64.exe
2013-7-31 10:49
0
雪    币: 993
活跃值: (442)
能力值: ( LV12,RANK:403 )
在线值:
发帖
回帖
粉丝
36
另外按MSDN的说明,第六个参数你至少应该定义为一个可读写的字符串变量再传递进去,否则可能引起错误,只所以没有出错是因为你的编译器在编译时可能把L"C:\\Users\\Administrator\\Desktop\\selfDestroy.exe"这个字符串放在了可读写的初始节内,尽管这样,它仍有可能被改变,导致下次循环时送进去的参数就不是你设想的这个字符串,还是尽量遵守API的调用说明吧。
lpCommandLine [in, out, optional]
The command line to be executed. The maximum length of this string is 1024 characters. If lpApplicationName is NULL, the module name portion of lpCommandLine is limited to MAX_PATH characters.
The function can modify the contents of this string. Therefore, this parameter cannot be a pointer to read-only memory (such as a const variable or a literal string). If this parameter is a constant string, the function may cause an access violation.
2013-7-31 10:55
0
雪    币: 2676
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
37
那就明显是第三方泄漏咯。
2013-7-31 11:13
0
雪    币: 38
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
38
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);       
               
                int  unicodeLen = ::MultiByteToWideChar( CP_ACP,0,(LPCSTR)&pcName,-1,NULL,0 ); //ascii转unicode
                wchar_t* pUnicode=(wchar_t*)calloc(unicodeLen+1,sizeof(wchar_t));               
                ::MultiByteToWideChar( CP_ACP,0,(LPCSTR)&pcName,-1,(LPWSTR)pUnicode,unicodeLen );

                BOOL abc;       
                abc=CreateProcessWithLogonW((LPCWSTR)L"abc",(LPCWSTR)pUnicode,(LPCWSTR)L"1",NULL,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);

                }       
                free(pUnicode);

        }

}

这是转成unicode后的,结果还是只有泄漏
2013-7-31 11:18
0
雪    币: 112
活跃值: (57)
能力值: ( LV12,RANK:200 )
在线值:
发帖
回帖
粉丝
39
您说的在理, LZ太粗心了.
我已经在20楼给他改了一个Demo.
但是我这, CreateProcessWithLogonW 会失败, 错误码0x422.
实验我做不下去了.
2013-7-31 11:26
0
雪    币: 38
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
40
都说函数第二个参数你不能填NULL啊,填上你的计算机名啊,右键我的电脑复制上去就ok了啊
2013-7-31 11:32
0
雪    币: 112
活跃值: (57)
能力值: ( LV12,RANK:200 )
在线值:
发帖
回帖
粉丝
41
我这里失败啊, 返回错误码0x422.
实验做不下去了.
用的是你贴出的代码, 实验环境都一样。
将用户名,口令, 需要建立的PE换成我这的.

你看下面的代码有啥问题? 在我这返回的错误是0x422.

// srcBad.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <windows.h>

/// build on vs2008, unicode console

/// @note
/// 测试环境, administrator 用户登录
/// 新建一个用户 usr_test, 以用户usr_test登录一次, 在usr_test用户环境下, 运行此程序
/// 以标准账户 usr_test 建立一个进程

/// usr_test用户已经登录过一次
/// CreateProcessWithLogonW Error Rc = 0x422
/// 无法启动服务,原因可能是已被禁用或与其相关联的设备没有启动。 

#define G_LOGIN_NAME    L"usr-test"
#define G_LOGIN_PWD     L"1"
#define G_PROG_NAME     L"d:\\ProgTobeRun.exe"

int _tmain(int argc, _TCHAR* argv[])
{
    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);  

        int  unicodeLen = ::MultiByteToWideChar( CP_ACP,0,(LPCSTR)&pcName,-1,NULL,0 ); //ascii转unicode
        wchar_t* pUnicode=(wchar_t*)calloc(unicodeLen+1,sizeof(wchar_t));    
        ::MultiByteToWideChar( CP_ACP,0,(LPCSTR)&pcName,-1,(LPWSTR)pUnicode,unicodeLen );

        BOOL abc;  
        abc=CreateProcessWithLogonW(
            (LPCWSTR)G_LOGIN_NAME,
            (LPCWSTR)pUnicode,
            (LPCWSTR)G_LOGIN_PWD,
            NULL,
            NULL,
            (LPWSTR)G_PROG_NAME,
            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);

        }  
        else
        {
            /// 失败 CreateProcessWithLogonW FALSE, 错误码 0x422
            /// 编译成x86, 启动x86的PE失败
            /// 编译成x64, 启动x64的PE失败
            /// UAC都关了, 在Administrator用户环境做的测试
            _tprintf(L"GetLastError = 0x%X\r\n", GetLastError());
        }

        free(pUnicode);

    }

    getwchar();
	return 0;
}

2013-7-31 11:54
0
雪    币: 155
活跃值: (20)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
42
看句柄用procexp啊,用个什么山寨的xuetr嘛
2013-7-31 12:38
0
雪    币: 112
活跃值: (57)
能力值: ( LV12,RANK:200 )
在线值:
发帖
回帖
粉丝
43
我知道为啥返回0x422了。
LastError 提示说服务没启动, 我想起本机用360Safe禁止了很多系统服务.
用360Safe将被禁用的系统服务都开启, 这回可以看到 CreateProcessWithLogonW 的效果了~~
2013-7-31 13:38
0
雪    币: 38
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
44
while(true)效果有目共睹就好
2013-7-31 14:42
0
雪    币: 112
活跃值: (57)
能力值: ( LV12,RANK:200 )
在线值:
发帖
回帖
粉丝
45
我已经测试完了, 没有你说的所谓句柄产泄漏问题。
我正在整理测试报告,一会贴个URL, 有空你去看看。

只能说你太粗心~~
2013-7-31 15:13
0
雪    币: 38
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
46
你说谎!!!!!!!!!!!!!任务管理器的性能选项卡下的系统句柄数一直几百几百地增加,360上的绿色的小球也可以看到内存使用一直增加!死循环是这样的,你别搞其他花样了
2013-7-31 15:16
0
雪    币: 38
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
47
难道因为我这个selfDestroy?改掉后缀名试试?换成exe
上传的附件:
2013-7-31 15:33
0
雪    币: 112
活跃值: (57)
能力值: ( LV12,RANK:200 )
在线值:
发帖
回帖
粉丝
48
实验做完了,请bdwdd光临指导~
实验结论: 使用CreateProcessWithLogonW, 没有句柄泄漏情况.

experiment : test CreateProcessWithLogonW

http://bbs.pediy.com/showthread.php?p=1204803#post1204803
2013-7-31 15:53
0
雪    币: 112
活跃值: (57)
能力值: ( LV12,RANK:200 )
在线值:
发帖
回帖
粉丝
49
就算我会说谎,程序是不会说谎的。
大佬啊,谁以后还会回您的贴??
还有谁敢深入的和您讨论问题啊??

我以后只能和你说一句话,bdwdd的技术水平真高, 为人真谦虚,人品刚刚的.
2013-7-31 16:47
0
雪    币: 220
活跃值: (117)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
50
1.用ARK看句柄表
2.怀疑字符串操作存在问题。
2013-7-31 22:59
0
游客
登录 | 注册 方可回帖
返回
//