设为主页 | 加入收藏 | 繁體中文

再谈进程与端口的映射


  OUT PULONG ReturnLength OPTIONAL
  };
  (这个函数布局Microsoft没有公然,拜见Gary Nebbett<>)
  第一个参数是一个枚举常数,设置要查询的系统信息范例,ZwQuerySystemInformation支持54个系统信息的查询,我们要用到的
  是它的第16号功能,进行SystemHandleInformation查询.
  SYSTEM_HANDLE_INFORMATION布局界说如下:
  typedef struct _SYSTEM_HANDLE_INFORMATION{
  ULONG ProcessID;        //进程的标识ID
  UCHAR ObjectTypeNumber;        //对象范例
  UCHAR Flags;             //0x01 = PROTECT_FROM_CLOSE,0x02 = INHERIT
  USHORT Handle;             //对象句柄的数值
  PVOID  Object;            //对象句柄所指的内核对象地点
  ACCESS_MASK GrantedAccess;      //创建句柄时所准许的对象的拜访权
  }SYSTEM_HANDLE_INFORMATION, * PSYSTEM_HANDLE_INFORMATION;
  (这个函数布局Microsoft没有公然,拜见Gary Nebbett<>)
  第二个参数输入查询的结果
  第三个参数设置缓冲区的长度
  第四个参数前往函数正确实行必要的缓冲区的大小
  代码如下:
  #define SystemHandleInformation 16
  PULONG GetHandleList()
  {
  ULONG cbBuffer = 0x1000;    //先设定一个较小的缓冲空间
  PULONG pBuffer = new ULONG[cbBuffer]; //分派内存
  NTSTATUS Status;
  do
  {
  Status = ZwQuerySystemInformation(
  SystemHandleInformation,
  pBuffer, cbBuffer * sizeof * pBuffer, NULL);
  if (Status == STATUS_INFO_LENGTH_MISMATCH)
  {
  //要是前往的错误信息为缓冲区长度不敷,那么重新分派内存
  delete [] pBuffer;
  pBuffer = new ULONG[cbBuffer *= 2];
  }
  else if (!NT_SUCCESS(Status))
  {
  //要是是其他错误信息,前往
  delete [] pBuffer;
  return false;
  }
  }
  while (Status == STATUS_INFO_LENGTH_MISMATCH);
  return pBuffer;
  }
  因为要是一个进程翻开了端口,那么它肯定会建立范例为\Device\Tcp和\Device\Udp的内核对象,以是,我们在以后进程中翻开
  上述的两个内核对象,在翻开的同时生存了翻开的句柄,如许,我们可以在上面获得的句柄列表中的以后进程中查找对象句柄的
  数值和我们生存的两个翻开的内核对象的句柄数值相同的句柄,并得到其句柄所指向的内核对象的地点.代码如下:
  DWORD TcpHandle;
  DWORD UdpHandle;
  DWORD GetTcpUdpObject(PULONG pBuffer,HANDLE pHandle,DWORD ProcessId)
  {
  DWORD objTYPE1,objTYPE2,HandleObject;
  PSYSTEM_HANDLE_INFORMATION pProcesses = (PSYSTEM_HANDLE_INFORMATION)(pBuffer+1);
  for (i=0;i< * pBuffer;i++)
  {
  if ((pProcesses[i].ProcessID) == ProcessId)
  {
  objTYPE1 = (DWORD)hDeviceTcpUdp;
  objTYPE2 = (DWORD)pProcesses[i].Handle;
  if(objTYPE1==objTYPE2)
  {
  HandleObject = (DWORD)pProcesses.Object;
  return HandleObject;
  }
  }
  return 0;
  }
  这个内核对象地点是一个线性地点,我们必要把这个地点转换为物理地点,并得到一些相关的数据.在fport中,换算是如许进行的:
  (详细形貌见WebCrazy的文章<<小议Windows NT/2000的分页机制>>)
  void * NewmapPhy;
  void GetPTE(DWORD objAddress)
  {
  DWORD physmemBuff;
  DWORD newAddress1,newAddress2,newAddress3,newAddress4;
  DWORD * newAddress;
  physmemBuff = (DWORD)pMapPhysicalMemory;
  newAddress1 = physmemBuff+(objAddress>>0x16)*4;
  newAddress = (DWORD *)newAddress1;
  newAddress1 = * newAddress;
  newAddress2 = objAddress & 0x3FF000;
  newAddress3 = newAddress1 & 0x0FFFFF000;
  newAddress4 = newAddress2 + newAddress3;
  NewmapPhy = MapViewOfFile(ghPhysicalMemory,FILE_MAP_READ,0,newAddress4,0x1000);
  //重新映射物理内存,得到当火线性地点所指向的PTE的物理地点内容
  }
  然后在根据内核对象的线性地点得到这个地点所指向的物理页,得到体现以后内核对象内容的页,其布局如下:
  typedef struct {
  ULONG Present;
  ULONG WriteTable;
  ULONG User;
  ULONG WriteThru;
  ULONG NoCache;
  ULONG Accessed;
  ULONG Dirty;
  ULONG PageSize;
  ULONG Global;
  ULONG Available;
  ULONG Pfn;
  } PTE, *PPTE;
  (注:我不克不及包管这个布局的正确性,但我们只会用到其中的两个值,对程序来说,这个布局是可以工作的,^_^)
  代码如下:
  ULONG CurrWriteTable;
  ULONG NoCache;
  void GetMustPar(DWORD objAddress)
  {
  DWORD CurrAddress;
  CurrAddress = objAddress & 0xFFF;
  PPTE pte = (PPTE)(VOID *)((DWORD)NewmapPhy+CurrAddress);
  CurrWriteTable = pte->WriteTable;
  CurrNoCache = Pte->NoCache;
  }
  好了,我们现在想要得到的都曾经得到了,下面必要做的是遍历进程,用每一个进程中的每一个句柄(呵呵,不是每一个句柄,
  在Windows NT下,\Device\Tcp和\Device\Udp的句柄范例值为0x16,在Windows 2000下这个值为0x1A)的焦点地点用上面所描
  述的办法得到其PTE内容,得到其WriteTable值,要是与内核对象\Device\Tcp和\Device\Udp相等,那么这个句柄就有大概翻开
  了一个端口,再对这个句柄进行确认,就可以了.确认的代码如下:
  typedef struct _TDI_CONNECTION_INFO {
  ULONG          State;
  ULONG          Event;
  ULONG          TransmittedTsdus;
  ULONG          ReceivedTsdus;
  ULONG          TransmissionErrors;
  ULONG          ReceiveErrors;
  LARGE_INTEGER  Throughput;
  LARGE_INTEGER  Delay;
  ULONG          SendBufferSize;
  ULONG          ReceiveBufferSize;
  BOOLEAN        Unreliable;
  } TDI_CONNECTION_INFO, *PTDI_CONNECTION_INFO;
  typedef struct _TDI_CONNECTION_INFORMATION {
  LONG   UserDataLength;
  PVOID  UserData;
  LONG   OptionsLength;
  PVOID  Options;
  LONG   RemoteAddressLength;
  PVOID  RemoteAddress;
  } TDI_CONNECTION_INFORMATION, *PTDI_CONNECTION_INFORMATION;
  (以上布局见tdi.h)
  void GetOpenPort(DWORD dwProcessesID,USHORT Handle,int NoCache)
  //dwProcessesID为进程标识ID
  //Handle为进程翻开的句柄,而且颠末比较为\Device\Tcp或\Device\Udp范例
  //NoCache为PTE布局中的一个值
  {
  HANDLE hProc,DupHandle=NULL;
  HANDLE hEven=NULL;
  OVERLAPPED overlap;
  u_short openport;
  int i=0;
  char procName[256]={0};
  int  portflag=0;
  overlap.Internal = 0;
  overlap.InternalHigh = 0;
  overlap.Offset = 0;
  overlap.OffsetHigh = 0;
  hEven=CreateEvent(0,1,0,0);
  overlap.hEvent = hEven;
  hProc = OpenProcess(PROCESS_DUP_HANDLE,
  0,
  dwProcessesID);
  if(hProc)
  {
  DuplicateHandle(hProc,
  (HANDLE)Handle,
  GetCurrentProcess(),
  &DupHandle,
  0,
  FALSE,
  2);
  CloseHandle( hProc );
  if(DupHandle)
  {
  TDI_CONNECTION_INFO    TdiConnInfo={0};
  TDI_CONNECTION_INFORMATION TdiConnInformation={0};
  DWORD dwRetu=0;   
  if(NoCache==0x2)
  {
  TdiConnInformation.RemoteAddressLength= 4;
  if(DeviceIoControl(DupHandle,0x210012,
  &TdiConnInformation,sizeof(TdiConnInformation),
  &TdiConnInfo,sizeof(TdiConnInfo),
  0,&overlap))
  //进行TDI查询,得到连接的相关信息
  {
  openport = ntohs((u_short)TdiConnInfo.ReceivedTsdus);
  procname = GetProcName(dwProcessesID);  //得到进程标识ID的进程名称
  printf("PID = %4d ProcessName = %15s PORT = %4d\n",dwProcessesID,procName,openport);
  }
  }
  if(NoCache==0x1)
  {
  TdiConnInformation.RemoteAddressLength= 3;
  if(DeviceIoControl(DupHandle,0x210012,
  &TdiConnInformation,sizeof(TdiConnInformation),
  &TdiConnInfo,sizeof(TdiConnInfo),
  0,&overlap))
  //进行TDI查询,得到连接的相关信息
  {
  openport = ntohs((u_short)TdiConnInfo.ReceivedTsdus);
  procname = GetProcName(dwProcessesID);  //得到进程标识ID的进程名称
  printf("PID = %4d ProcessName = %15s PORT = %4d\n",dwProcessesID,procName,openport);
  }
  }
  }
  }
  CloseHandle(hEven);
  CloseHandle(DupHandle);
  }
  以上是我对fport.exe的分析及其实当代码,演示程序可以从whitecell.org下载,要是你发明有问题,请通知我,^_^
  参考:
  fport.exe
  Gary Nebbett<>
  WebCrazy<<小议Windows NT/2000分页机制>>
  NTDDK
 


    文章作者: 福州军威计算机技术有限公司
    军威网络是福州最专业的电脑维修公司,专业承接福州电脑维修、上门维修、IT外包、企业电脑包年维护、局域网网络布线、网吧承包等相关维修服务。
    版权声明:原创作品,允许转载,转载时请务必以超链接形式标明文章原始出处 、作者信息和声明。否则将追究法律责任。

TAG:
评论加载中...
内容:
评论者: 验证码: