首页
社区
课程
招聘
关于DebugActiveProcess函数不能成功执行的问题!!!
发表于: 2005-8-20 21:47 12968

关于DebugActiveProcess函数不能成功执行的问题!!!

2005-8-20 21:47
12968
写了一个对特定进程的调试程序,思路如下:
首先用FindWindow得到窗口句柄
再用GetWindowThreadProcessId得到进程ID和主线程ID
最后用OpenProcess(PROCESS_ALL_ACCESS权限)得到进程句柄,这些函数经测试都执行无误。
然后想用DebugActiveProcess来绑定这个进程进行调试,但这个函数总是执行不成功,返回0,看了一些资料说此函数出错多是由于进程权限的问题,可是我打开进程时用的是PROCESS_ALL_ACCESS权限,应该不存在这个问题啊!请有这方面编程经验的高手帮助解决一下。。。

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (13)
雪    币: 1852
活跃值: (504)
能力值: (RANK:1010 )
在线值:
发帖
回帖
粉丝
2
DebugActiveProcess我没用过,不好说
不过若要调试一个进程不必要这个:
DEBUG_EVENT devent ;
while ( isContinue )
{
  if ( WaitForDebugEvent( &devent, 100) )
  {
    switch ( devent.dwDebugEventCode )
    {
    }
    ContinueDebugEvent ( hProcess, hThread, DBG_CONTINUE...) ;
  }
}

要注意的是CreateProcess时要用DEBUG_ONLY_THIS_PROCESS标志
2005-8-21 00:08
0
雪    币: 1852
活跃值: (504)
能力值: (RANK:1010 )
在线值:
发帖
回帖
粉丝
3
顺便灌水一贴

你的名字不错, "好男人"
我挺喜欢这首歌
2005-8-21 00:10
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
呵呵,过奖了。取这个名字倒不是因为歌的缘故,而且本人也不太喜欢听歌,之所以取这个名字是因为比较喜欢成龙的电影,<<一个好人>>,咳,取个名也不是件轻松事啊,我就经常的套用成龙大哥的电影了,有点侵权,不过成龙大哥可管不了这摸多了。。。呵呵。。。

接着上面,如果要是自己创建一个进程并运行的话,当然用CreateProcess函数很好了,进程在运行之前就有一个CREATE_PROCESS_DEBUG_EVENT,可是如果你不是自己创建进程,而是一个已经运行的进程,你怎样调试啊?那就只能是先取得这个进程的控制权,所以我先用FindWindow,GetWindowThreadProcessId,OpenProcess这些函数来取得这个进程的进程句柄.进程ID,主线程ID(哪位知道如果已知前面三个值来得到主线程句柄的方法,麻烦告一声),有了这个进程的控制权以后再强行的用DebugActiveProcess来使它与调试程序捆绑起来,可是就在这函数老是执行失败,实在想不出为什么函数会执行失败。。。
2005-8-21 07:42
0
雪    币: 1852
活跃值: (504)
能力值: (RANK:1010 )
在线值:
发帖
回帖
粉丝
5
------------------------------------------------------
引用MSDN:
However, on Windows NT, DebugActiveProcess can fail if the target process was created with a security descriptor that grants the debugger anything less than full access. Note that if the debugging process has the SE_DEBUG_NAME privilege granted and enabled, it can debug any process.
―――――――――――――――――――――――――----
提升调试进程SE_DEBUG_NAME权限即可
2005-8-21 10:07
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
已经试了,还是不行啊!看看我提升进程权限的函数是否正确?
BOOL UpdateProcessPrivilege(HANDLE hProcess,LPCTSTR lpPrivilegeName)
{
        HANDLE hToken;
        if(::OpenProcessToken(hProcess,TOKEN_ALL_ACCESS,&hToken))
        {
                LUID destLuid;
                if(::LookupPrivilegeValue(NULL,lpPrivilegeName,&destLuid))
                {
                        TOKEN_PRIVILEGES TokenPrivileges;
                        TokenPrivileges.PrivilegeCount=1;
                        TokenPrivileges.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;
                        TokenPrivileges.Privileges[0].Luid=destLuid;
                        if(::AdjustTokenPrivileges(hToken,FALSE,&TokenPrivileges,0,NULL,NULL))
                        {
                                return TRUE;
                        }
                }
        }
return FALSE;
}

调用:UpdateProcessPrivilege(GetCurrentProcess(),SE_DEBUG_NAME);

这段代码在我的程序里是执行成功了,但DebugActiveProcess还是返回FALSE
晕了,天好黑啊。。。
2005-8-21 12:03
0
雪    币: 1852
活跃值: (504)
能力值: (RANK:1010 )
在线值:
发帖
回帖
粉丝
7
转文一篇:HOWTO: How to Obtain a Handle to Any Process with SeDebugPrivilege
来源: VS.NET MSDN

#define RTN_OK 0
#define RTN_USAGE 1
#define RTN_ERROR 13

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

BOOL SetPrivilege(
    HANDLE hToken,          // token handle
    LPCTSTR Privilege,      // Privilege to enable/disable
    BOOL bEnablePrivilege   // TRUE to enable.  FALSE to disable
    );

void DisplayError(LPTSTR szAPI);

int main(int argc, char *argv[])
{
    HANDLE hProcess;
    HANDLE hToken;
    int dwRetVal=RTN_OK; // assume success from main()

    // show correct usage for kill
    if (argc != 2)
    {
        fprintf(stderr,"Usage: %s [ProcessId]\n", argv[0]);
        return RTN_USAGE;
    }

    if(!OpenProcessToken(
            GetCurrentProcess(),
            TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
            &hToken
            )) return RTN_ERROR;

    // enable SeDebugPrivilege
    if(!SetPrivilege(hToken, SE_DEBUG_NAME, TRUE))
    {
        DisplayError("SetPrivilege");

        // close token handle
        CloseHandle(hToken);

        // indicate failure
        return RTN_ERROR;
    }

   // open the process
    if((hProcess = OpenProcess(
            PROCESS_ALL_ACCESS,
            FALSE,
            atoi(argv[1]) // PID from commandline
            )) == NULL)
    {
        DisplayError("OpenProcess");
        return RTN_ERROR;
    }

    // disable SeDebugPrivilege
    SetPrivilege(hToken, SE_DEBUG_NAME, FALSE);

    if(!TerminateProcess(hProcess, 0xffffffff))
    {
        DisplayError("TerminateProcess");
        dwRetVal=RTN_ERROR;
    }

    // close handles
    CloseHandle(hToken);
    CloseHandle(hProcess);

    return dwRetVal;
}

BOOL SetPrivilege(
    HANDLE hToken,          // token handle
    LPCTSTR Privilege,      // Privilege to enable/disable
    BOOL bEnablePrivilege   // TRUE to enable.  FALSE to disable
    )
{
    TOKEN_PRIVILEGES tp;
    LUID luid;
    TOKEN_PRIVILEGES tpPrevious;
    DWORD cbPrevious=sizeof(TOKEN_PRIVILEGES);

    if(!LookupPrivilegeValue( NULL, Privilege, &luid )) return FALSE;

    // 
    // first pass.  get current privilege setting
    // 
    tp.PrivilegeCount           = 1;
    tp.Privileges[0].Luid       = luid;
    tp.Privileges[0].Attributes = 0;

    AdjustTokenPrivileges(
            hToken,
            FALSE,
            &tp,
            sizeof(TOKEN_PRIVILEGES),
            &tpPrevious,
            &cbPrevious
            );

    if (GetLastError() != ERROR_SUCCESS) return FALSE;

    // 
    // second pass.  set privilege based on previous setting
    // 
    tpPrevious.PrivilegeCount       = 1;
    tpPrevious.Privileges[0].Luid   = luid;

    if(bEnablePrivilege) {
        tpPrevious.Privileges[0].Attributes |= (SE_PRIVILEGE_ENABLED);
    }
    else {
        tpPrevious.Privileges[0].Attributes ^= (SE_PRIVILEGE_ENABLED &
            tpPrevious.Privileges[0].Attributes);
    }

    AdjustTokenPrivileges(
            hToken,
            FALSE,
            &tpPrevious,
            cbPrevious,
            NULL,
            NULL
            );

    if (GetLastError() != ERROR_SUCCESS) return FALSE;

    return TRUE;
}

void DisplayError(
    LPTSTR szAPI    // pointer to failed API name
    )
{
    LPTSTR MessageBuffer;
    DWORD dwBufferLength;

    fprintf(stderr,"%s() error!\n", szAPI);

    if(dwBufferLength=FormatMessage(
                FORMAT_MESSAGE_ALLOCATE_BUFFER |
                FORMAT_MESSAGE_FROM_SYSTEM,
                NULL,
                GetLastError(),
                GetSystemDefaultLangID(),
                (LPTSTR) &MessageBuffer,
                0,
                NULL
                ))
    {
        DWORD dwBytesWritten;

        // 
        // Output message string on stderr
        // 
        WriteFile(
                GetStdHandle(STD_ERROR_HANDLE),
                MessageBuffer,
                dwBufferLength,
                &dwBytesWritten,
                NULL
                );

        // 
        // free the buffer allocated by the system
        // 
        LocalFree(MessageBuffer);
    }
} 
2005-8-21 14:02
0
雪    币: 1852
活跃值: (504)
能力值: (RANK:1010 )
在线值:
发帖
回帖
粉丝
8
AdjustTokenPrivileges(hToken,FALSE,&TokenPrivileges,0,NULL,NULL)
注意下第四个参数:sizeof(TOKEN_PRIVILEGES);

你测试一下,是不是这里的问题?
2005-8-21 14:29
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
不是那个参数的问题,那个参数是跟他后面的参数相联系的,如果他后面的参数为NULL的话,那摸这个参数就可以为0。
2005-8-22 08:13
0
雪    币: 1852
活跃值: (504)
能力值: (RANK:1010 )
在线值:
发帖
回帖
粉丝
10
2005-8-22 10:58
0
雪    币: 1852
活跃值: (504)
能力值: (RANK:1010 )
在线值:
发帖
回帖
粉丝
11
测试了一下:
你的程序有这么一句
OpenProcessToken(hProcess,TOKEN_ALL_ACCESS,&hToken)
应该改为OpenProcessToken(GetCurrentProcess(),.....
要调整权限的是当前进程,而不是目标进程
这样就OK 了
2005-8-22 11:54
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
呵呵,终于找到原因了,不是由于权限的问题,根本原因就是DebugActiveProcess函数的dwProcessID参数根本就没有传进来,当然函数执行不成功了。
我这个程序是这样做的,一个基于远程钩子的线程钩子dll函数,我把得到dwProcessID的GetWindowThreadProcessID函数放在了这个dll里面,dwProcessID做为这个dll的全局变量,而使用这个dwProcessID做为参数的DebugActiveProcess函数是放在了钩子回调函数中,所以这个dwProcesID在链接时要设置成共享段,并且dwProcessID要初始化,而我的程序中恰恰就忘了给他赋个NULL,晕啊。。。
我的程序下一步就是要调试了,用THREADCONTEXT,但GetThreadContext函数要主线程句柄,我又不是用CreateProcess,哪来的主线程句柄啊!搜了一下,有篇文章说了:从ThreadID得不到ThreadHandle,有了ThreadHandle,你还不能干什么事啊?所以Microsoft决不会给你这个接口。。。看来是没有希望了,正打算重新用CreateProcess来做,但这样就会涉及到很多继承方面的东西(要调试的进程会创建新的进程),看看吧。。。如果哪位知道由ThreadID得到ThreadHandle的方法,麻烦告一声,在这里先谢谢了!!!

“如果只是索取,资源终将枯竭,只有大家都把经验共享出来,我们的思维才会充满活力。”真理啊!!!昨天看了一个关于Richard Stallman的视频,对自由软件又有进一步的了解,不管你对他从事的事业抱什么样的看法,这样的人都值得尊敬。。。
2005-8-22 12:02
0
雪    币: 1852
活跃值: (504)
能力值: (RANK:1010 )
在线值:
发帖
回帖
粉丝
13
用DuplicateHandle可以将 进程/线程伪句柄 转化为 进程/线程实句柄
2005-8-22 12:11
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
DuplicateHandle好象不行啊,他可以把假句柄替换成真句柄,但我只能得到线程ID,我做不到在这个线程中用GetCurrentThread得到假句柄。有一个OpenThread函数可以实现线程ID到线程句柄的转换,只是这个函数只能在2000 server以上的os中使用!!!
2005-8-23 10:15
0
游客
登录 | 注册 方可回帖
返回
//