以下是ShutGun写的关于进程与端口映射的代码,可以列出哪些进程打开了哪些端口,现我改写了下,当我循环输入viewport命令时以前保存在我分配的缓冲区里的所有系统当前的句柄好像并没有释放的,再次输入viewport你就会发现这个进程里的句柄数翻倍的,请问该怎么关闭前面的句柄呢~~~~???#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#include <Aclapi.h>#pragma comment ( lib, "ws2_32.lib" )// NtQuerySystemInformation record type 16
#define NT_HANDLE_LIST           16
#define OBJECT_TYPE_SOCKET       0x1A
#define MAX_HANDLE_LIST_BUF      0x200000// 定义HanleInfo数据结构
typedef struct _HandleInfo
{
  USHORT dwPid;
  USHORT CreatorBackTraceIndex; 
  BYTE ObjType;
  BYTE HandleAttributes;
  USHORT HndlOffset;
  DWORD dwKeObject;
  ULONG GrantedAccess;
}HANDLEINFO, *PHANDLEINFO;// 申明NtQuerySystemInformation()函数
typedef DWORD (CALLBACK* NTQUERYSYSTEMINFORMATION)( DWORD, PDWORD, DWORD, PVOID );
NTQUERYSYSTEMINFORMATION NtQuerySystemInformation;// 判断SOCKET类型的数组
char szSockType[6][6] = { "NUL", "TCP", "UDP", "RAW", "RDM", "SEQ" };//--------------------------------------------------------------------------------------------
//
// RaisePrivleges()函数用来提升本进程的特权
//
//--------------------------------------------------------------------------------------------
bool RaisePrivleges( HANDLE hToken, char *pPriv )
{
TOKEN_PRIVILEGES tkp;
if ( !LookupPrivilegeValue( NULL, pPriv, &tkp.Privileges[0].Luid ) )
  {
    printf( "LookupPrivilegeValue Error:%d\n", GetLastError() );
    return false;
  }tkp.PrivilegeCount = 1;
tkp.Privileges[0].Attributes |= SE_PRIVILEGE_ENABLED;
int iRet = AdjustTokenPrivileges(hToken,false,&tkp,0,(PTOKEN_PRIVILEGES)NULL,0);if ( iRet == NULL )//AdjustTokenPrivileges函数调用失败
{
  printf( "AdjustTokenPrivileges Error:%d\n", GetLastError() );
  return false;
}
else//AdjustTokenPrivileges调用成功
{//使用GetLastError()获得返回值
  iRet = GetLastError();
  switch ( iRet )
  {
    case ERROR_NOT_ALL_ASSIGNED://未指派所有的特权
      printf( "AdjustTokenPrivileges ERROR_NOT_ALL_ASSIGNED\n" );
      return false;
    case ERROR_SUCCESS://成功地指派了所有的特权
      return true;
    default://不知名的错误
      printf( "AdjustTokenPrivileges Unknow Error:%d\n", iRet );
      return false;
  }
}
}//end of RaisePrivleges//--------------------------------------------------------------------------------------------
//
// AdjustDacl用来调整目标进程的DACL
// 
//--------------------------------------------------------------------------------------------
void AdjustDacl( HANDLE hProcess )
{
SID world = { SID_REVISION, 1, SECURITY_WORLD_SID_AUTHORITY, 0 };LPTSTR ptstrName = (LPTSTR)&world;EXPLICIT_ACCESS ea ={ STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,//声明一个访问权
                      SET_ACCESS,//指出一个ACCESS_ALLOWED_ACE结构同意声明的权利
                      NO_INHERITANCE,//
                      {0, NO_MULTIPLE_TRUSTEE,TRUSTEE_IS_SID,TRUSTEE_IS_USER,ptstrName} };
ACL * pdacl = 0;if ( SetEntriesInAcl(1, &ea, 0, &pdacl) != ERROR_SUCCESS )
  printf( "SetEntriesInAcl Error:%d", GetLastError() );if ( SetSecurityInfo(hProcess,SE_KERNEL_OBJECT,DACL_SECURITY_INFORMATION,0,0,pdacl,0)!=                                                                                   ERROR_SUCCESS )
  printf( "SetSecurityInfo Error:%d", GetLastError() );LocalFree(pdacl);
}//end of AdjustDacl

解决方案 »

  1.   

    //--------------------------------------------------------------------------------------------
    //
    //Qport()
    //主调函数
    //--------------------------------------------------------------------------------------------
    DWORD WINAPI qport( void *s )
    {
    printf( "\t=*= GPort Beta1 ([email protected]) =*=\n\n" );int iRet;
    WSADATA wsaData;DWORD (__stdcall *GMFNE)(HANDLE hProcess,HMODULE hModule,LPTSTR lpFilename,DWORD nSize);
    //嘿嘿!!这里是动态的加载了GetModuleFileNameExA函数,这个在后面有用到的
    iRet = WSAStartup( MAKEWORD(1,1), &wsaData );//初始化WSAStartup
    if ( iRet )
      printf( "WSAStartup Error:%d\n", GetLastError() );HANDLE hCurrentProc = GetCurrentProcess();//得到当前的进程
    HANDLE hToken;if(!OpenProcessToken(hCurrentProc,TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,&hToken))
      printf( "OpenProcessToken Error:%d\n", GetLastError() );else
      {
        if ( !RaisePrivleges( hToken, SE_DEBUG_NAME ) )
          printf( "SetPrivleges SE_DEBUG_NAME Error:%d\n", GetLastError() );
      }if ( hToken )
      CloseHandle( hToken );HMODULE hNtdll = NULL;hNtdll = LoadLibrary( "ntdll.dll" );if ( !hNtdll )
      {
        printf( "LoadLibrary( NTDLL.DLL ) Error:%d\n", GetLastError() );
        return false;
      }NtQuerySystemInformation = (NTQUERYSYSTEMINFORMATION)GetProcAddress(hNtdll,"NtQuerySystemInformation");if ( !NtQuerySystemInformation )
      {
        printf( "GetProcess( NtQuerySystemInformation ) Error:%d\n", GetLastError() );
        return false;
      }HMODULE hPsapi=LoadLibrary("PSAPI");if(!hPsapi)
      {
        printf("Cannot load PSAPI.\n");
        return 0;
      }GMFNE=(DWORD (__stdcall *) (HANDLE, HMODULE,LPTSTR,DWORD))GetProcAddress(hPsapi,"GetModuleFileNameExA");//加载GetModuleFileNameExAif(!GMFNE)
      {
        printf("Cannot GetProcess(GetModuleFileNameExA) Error:%d\n", GetLastError() );
        return 0;
      }DWORD dwNumBytes = MAX_HANDLE_LIST_BUF;
    PDWORD pdwHandleList = (PDWORD)malloc( dwNumBytes );//分配空间,必需足够大if ( !pdwHandleList )
      {
        printf( "Malloc for Handle List Error:%d\n", GetLastError() );
        return false;
      }DWORD dwNumBytesRet = 0;
    iRet = (*NtQuerySystemInformation)(NT_HANDLE_LIST,pdwHandleList,dwNumBytes,&dwNumBytesRet);//使用未公开的API--NtQuerySystemInformation. NtQuerySystemInformation这个函数有四个参数,第一个参数是dwRecordType,这个参数指定了我们所查询的系统信息类型,为了查询系统HANDLE列表,我们定义一个常量#define NT_HANDLE_LIST 16(这个数值我是查资料得到的,如果谁有更详细的资料,也请让我共享一下);第二个参数是一个指针,这个指针用来返回系统句柄列表,在调用NtQuerySystemInformation函数之前,必须为这个指针分配足够的内存空间,否则函数调用会出错;第三个参数是指定你为HandleList所分配的内存空间大小,单位是byte;第四个参数是NtQuerySystemInformation返回的HandleList的大小;如果NtQuerySystemInformation函数调用成功,返回值将是0. 一旦NtQuerySystemInformation函数调用成功,系统中所有的句柄将被存放在pdwHandleList所指向内存空间中,其中,pdwHandleList所指向的第一个32位数,是这个buf所包含的句柄数量,之后是顺序排列的句柄指针pHandleInfo,指向的是HANDLEINFO结构:这个结构也是未公开的,已在前面定义DWORD dwNumEntries;
    PHANDLEINFO pHandleInfo;if ( iRet )
      {
        printf( "NtQuerySystemInformation return %d, Error:%d\n",dwNumBytesRet,GetLastError() );
      }
    else
      {
        HANDLE hProc;
        dwNumEntries = pdwHandleList[0];
        pHandleInfo = (PHANDLEINFO)( pdwHandleList + 1 );    for ( DWORD i = 0; i < dwNumEntries; i++ )
        {
          if (   (pHandleInfo->ObjType == OBJECT_TYPE_SOCKET)//判端句柄类型是否为SOCKET句柄 
                    && 
                 (pHandleInfo->dwPid)  )//是否得到PID
          {
            hProc = OpenProcess( PROCESS_ALL_ACCESS,//WRITE_DAC,
                                 false,
                                 pHandleInfo->dwPid );//打开进程
              if ( hProc )
               {
                AdjustDacl( hProc );
                CloseHandle( hProc );
               }
              else
                printf( "OpenProcess(WRITE_DAC) %d Error:%d\n",pHandleInfo->dwPid,GetLastError());
          
            HANDLE hMyHandle = NULL;
            hProc = OpenProcess(PROCESS_ALL_ACCESS,//PROCESS_DUP_HANDLE,//用PROCESS_DUP_HANDLE访问标志使得可以用                                               //DuplicateHandle函数去复制句柄
                                true,//可以继承
                                pHandleInfo->dwPid );          if ( hProc )
              {
            DuplicateHandle( hProc,//指向源进程的句柄
                     (HANDLE)pHandleInfo->HndlOffset,//指向被复制的句柄
                     hCurrentProc,//指向得到复制句柄的进程
                     &hMyHandle,//用来存放复制的句柄的缓冲区
                     STANDARD_RIGHTS_REQUIRED,//复制句柄的访问请求
                     false,//指定为不可继承的
                     0 );//
            CloseHandle( hProc );
            //CloseHandle( (HANDLE)pHandleInfo->HndlOffset );
            }
            else
              printf( "OpenProcess %d Error:%d\n",pHandleInfo->dwPid,GetLastError());        if ( !hMyHandle )
            {
              Sleep( 0 );
            //printf( "DuplicateHandle PID=%4d HANDLE:%4d Error:%d\n",pHandleInfo->dwPid,pHandleInfo->HndlOffset, GetLastError() );
            }
            else
            {
              sockaddr_in name = {0};
              name.sin_family = AF_INET;
              int namelen = sizeof(sockaddr_in);
              SOCKET s = (SOCKET)hMyHandle;
              iRet = getsockname( s,(sockaddr*)&name,&namelen );//getsockname取得SOCKET的本地名          if ( iRet != SOCKET_ERROR )
              {
                int sockType = 0;
                int optlen = 4;
                char fn[128];
                iRet = getsockopt( s,//SOCKET名
                                   SOL_SOCKET,//工作层
                                   SO_TYPE,//哪种类型的SOCKET将被返回
                                   (char*)&sockType,//得到反回的请求的属性的缓冲区地址,这里得到的属性                                                //好像是以数值表示的 
                                   &optlen );
                hProc=OpenProcess(PROCESS_ALL_ACCESS,false,pHandleInfo->dwPid);
                GMFNE( hProc,//进程句柄
                       NULL,//模块句柄
                       fn,//用来得到返回的缓冲区
                       128);//GetModuleFileNameEx函数得到指定模块的真实路径
                CloseHandle( hProc );
                CloseHandle( hMyHandle );
                printf( "PID=%4d ---> PORT=%5d %s  %s\n",
                        pHandleInfo->dwPid,
                        ntohs( name.sin_port),
                        szSockType[sockType],
                        fn );
              }        }      }
        pHandleInfo++;
        }
      }if ( pdwHandleList )
      free( pdwHandleList );if ( hCurrentProc )
      CloseHandle( hCurrentProc );FreeLibrary(hPsapi);
    FreeLibrary(hNtdll);ExitThread(0);
    return 0;
    }
    int main()
    {
    char command[20];
    printf("please input the command: ");
    while(1)
    {
             gets(command);
             if( strcmp(command,"viewport")==0 )
             {
                      DWORD dwport=0;
                      CreateThread(NULL,0,qport,(LPVOID)1,0,&dwport);
             }
             if( strcmp(command,"exit")==0 )
             {
                      exit( 0 );
             }
             printf("please input the command: ");
    }
    }
      

  2.   

    那些Handle并不需要你去Close的,你的Buffer里只是存放关于这些Handle的信息,而且在线程函数里也把内存空间释放掉了。唯一值得怀疑的就是那个未公开的Api:NtQuerySystemInformation,Buffer的内容都是它填的……一点看法。
      

  3.   

    同意NowCan我也这么认为的,可怎么关闭呢~~???还有,explorer007(KKcat) 说的也有道理
      

  4.   

    不是很清楚,其实我很早就用过这个程序,但是运行总是出错,很奇怪。难道你们都能正常运行?
    进程端口关联已经讨论的很多了,而且这个方法也不好。
    http://www.xfocus.net/xfocus_doc.php
    你看看这个东西,能学到很多东西。
      

  5.   

    是的,我可以正常运行的,不过ShutGun的源代码只是一个单独的EXE,我把他改成循环后就发现了这问题请问NowCan你的错务是什么~~~????
      

  6.   

    晕 今天把你上面的代码运行了一下 没有出现你说的问题啊 一切正常 Windows Server Pack3你是什么系统啊?
      

  7.   

    呵呵~~~~~~!!!!怎段代码我是改过的~~~~!!!!不过不知你注意看了此程序进程中的句柄数没~~~????( 在任务管理器中看的 )每运行一次viewport句柄数都是翻备倍的~~~~!!!!