背景:
小弟在做个系统监视软件,其中遇到了些问题,需要大家帮忙~! 烦请知道的朋友告诉我,谢谢了!!问题:
1.每次去遍历进程的lsass.exe进程的Handle信息后,不能正常退出程序了,发现还有遍历此进程Handle的线程卡死了(具体原因不明),而且我用TerminateThread来关闭也不行(非权限问题,且进程管理器也不能终止进程).而我用iceSword(传说中的冰忍软件)用TerminateThread就能关闭。他这个TerminateThread是怎么实现的?2.每次遍历devnev.exe的加载模块信息后,程序退出的时候就会造成字符串非法操作!而其他的地程序就没有此问题!最后:祝大家新年快乐!

解决方案 »

  1.   


    void SystemHandleInformation::GetHandleAddress(DWORD dwHandleAddr,HANDLE_INFORMATION &handleInfo)
    {
    static TCHAR szTemp[32]={0}; wsprintf(szTemp,_T("%p"),dwHandleAddr);
    handleInfo.strAddr=szTemp;
    }HANDLE SystemHandleInformation::OpenProcess( DWORD processId )
    {
    // Open the process for handle duplication
    return ::OpenProcess( PROCESS_DUP_HANDLE, TRUE, processId );
    }HANDLE SystemHandleInformation::DuplicateHandle( HANDLE hProcess, HANDLE hRemote )
    {
    HANDLE hDup = NULL; // Duplicate the remote handle for our process
    ::DuplicateHandle( hProcess, hRemote, GetCurrentProcess(), &hDup, 0, FALSE, DUPLICATE_SAME_ACCESS ); return hDup;
    }//Information functions
    BOOL SystemHandleInformation::GetTypeToken( HANDLE h, string& str, DWORD processId )
    {
    ULONG size = 0x2000;
    UCHAR* lpBuffer = NULL;
    BOOL ret = FALSE; HANDLE handle;
    HANDLE hRemoteProcess = NULL;
    BOOL remote = processId != GetCurrentProcessId();

    if ( !NtDllStatus )
    return FALSE; if ( remote )
    {
    // Open the remote process
    hRemoteProcess = OpenProcess( processId );

    if ( hRemoteProcess == NULL )
    return FALSE; // Duplicate the handle
    handle = DuplicateHandle( hRemoteProcess, h );
    }
    else
    handle = h; // Query the info size
    INtDll::NtQueryObject( handle, 2, NULL, 0, &size ); lpBuffer = new UCHAR[size]; // Query the info size ( type )
    if ( INtDll::NtQueryObject( handle, 2, lpBuffer, size, NULL ) == 0 )
    {
    str = _T("");
    SystemInfoUtils::LPCWSTR2CString( (LPCWSTR)(lpBuffer+0x60), str ); ret = TRUE;
    } if ( remote )
    {
    if ( hRemoteProcess != NULL )
    CloseHandle( hRemoteProcess ); if ( handle != NULL )
    CloseHandle( handle );
    }

    if ( lpBuffer != NULL )
    delete [] lpBuffer; return ret;
    }BOOL SystemHandleInformation::GetType( HANDLE h, WORD& type, DWORD processId )
    {
    string strType; type = OB_TYPE_UNKNOWN; if ( !GetTypeToken( h, strType, processId ) )
    return FALSE; return GetTypeFromTypeToken( strType.c_str(), type );
    }BOOL SystemHandleInformation::GetTypeFromTypeToken( LPCTSTR typeToken, WORD& type )
    {
    const WORD count = 27;
    string constStrTypes[count] = 

    _T(""), _T(""), _T("Directory"), _T("SymbolicLink"), _T("Token"),
    _T("Process"), _T("Thread"), _T("Unknown7"), _T("Event"), _T("EventPair"), _T("Mutant"), 
    _T("Unknown11"), _T("Semaphore"), _T("Timer"), _T("Profile"), _T("WindowStation"),
    _T("Desktop"), _T("Section"), _T("Key"), _T("Port"), _T("WaitablePort"), 
    _T("Unknown21"), _T("Unknown22"), _T("Unknown23"), _T("Unknown24"),
    _T("IoCompletion"), _T("File") 
    }; type = OB_TYPE_UNKNOWN; for ( WORD i = 1; i < count; i++ )
    if ( constStrTypes[i] == typeToken )
    {
    type = i;
    return TRUE;
    }

    return FALSE;
    }BOOL SystemHandleInformation::GetName( HANDLE handle, string& str, DWORD processId )
    {
    WORD type = 0; if ( !GetType( handle, type, processId  ) )
    return FALSE; return GetNameByType( handle, type, str, processId );
    }BOOL SystemHandleInformation::GetNameByType( HANDLE h, WORD type, string& str, DWORD processId )
    {
    ULONG size = 0x2000;
    UCHAR* lpBuffer = NULL;
    BOOL ret = FALSE; HANDLE handle;
    HANDLE hRemoteProcess = NULL;
    BOOL remote = processId != GetCurrentProcessId();
    DWORD dwId = 0;

    if ( !NtDllStatus )
    return FALSE; if ( remote )
    {
    hRemoteProcess = OpenProcess( processId );

    if ( hRemoteProcess == NULL )
    return FALSE; handle = DuplicateHandle( hRemoteProcess, h );
    }
    else
    handle = h; // let's be happy, handle is in our process space, so query the infos :)
    switch( type )
    {
    case OB_TYPE_PROCESS:
    //GetProcessId( handle, dwId );

    //str.Format( _T("PID: 0x%X"), dwId );

    ret = TRUE;
    goto cleanup;
    break; case OB_TYPE_THREAD:
    //GetThreadId( handle, dwId ); //str.Format( _T("TID: 0x%X") , dwId );

    ret = TRUE;
    goto cleanup;
    break; case OB_TYPE_FILE:
    //ret = GetFileName( handle, str ); // access denied :(
    //if ( ret && str == _T("") )
    // goto cleanup;
    break; }; INtDll::NtQueryObject ( handle, 1, NULL, 0, &size ); // let's try to use the default
    if ( size == 0 )
    size = 0x2000; lpBuffer = new UCHAR[size]; if ( INtDll::NtQueryObject( handle, 1, lpBuffer, size, NULL ) == 0 )
    {
    SystemInfoUtils::Unicode2CString( (UNICODE_STRING*)lpBuffer, str );
    ret = TRUE;
    }

    cleanup: if ( remote )
    {
    if ( hRemoteProcess != NULL )
    CloseHandle( hRemoteProcess ); if ( handle != NULL )
    CloseHandle( handle );
    } if ( lpBuffer != NULL )
    delete [] lpBuffer;

    return ret;
    }
    实在很多,这些就是遍历进程打开handle信息的方法~
      

  2.   

    NtQueryObject,NtQuerySystemInformation这种用户态的函数用起来好像就是有这问题,有时候就卡死了。IceSword估计用的是某种kernel rootkit技术,太强大了。
      

  3.   

    When you query for object name on a pipe handle (opened for synchronous io, and where there are pending read operations) then your thread will hang. Permanently. And attempts to terminate the thread will possibly end in a bluescreen.
      

  4.   

    http://www.codeguru.com/forum/archive/index.php/t-359606.html