进程--端口关联(源代码)

//
// 作者 beiyu http://beiyu.bokee.com
// 内核态实现进程和端口关联,在WINDOWS2000.xp,2003下可以用。
// 感谢Leven公布了他的代码,增加了区分tcp,udp,增加了操作系统的兼容性
// 可以在Windows 2000, xp, 2003下面正常使用,编译环境Win2000DDK
// 使用妳的sys loader加载,使用Dbgview查看
// 如果你有什么改进,请email我: liang5158270@sina.com
//
//
#include <ntddk.h>
#include <string.h>

#define SystemHandleInformation 16
#define TCPUDP_FLAG   100
#define WIN2K_SOCKET_FLAG 0x1a //2k
#define WINXP_SOCKET_FLAG 0x1c //xp
#define WIN2K3_SOCKET_FLAG 0x1a //2k3
#define WIN2K_EPROCESS_NAMEOFFSET   0x1fc //2k
#define WINXP_EPROCESS_NAMEOFFSET   0x174 //xp
#define WIN2K3_EPROCESS_NAMEOFFSET   0x1fc //2k3

#define ObjectNameInformation 1
#define ObjectAllTypesInformation 3

/*
typedef struct _OBJECT_NAME_INFORMATION {
UNICODE_STRING Name;
} OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION;

typedef struct _OBJECT_TYPE_INFORMATION {
UNICODE_STRING Name;
ULONG ObjectCount;
ULONG HandleCount;
ULONG Reserved1[4];
ULONG PeakObjectCount;
ULONG PeakHandleCount;
ULONG Reserved2[4];
ULONG InvalidAttributes;
GENERIC_MAPPING GenericMapping;
ULONG ValidAccess;
UCHAR Unknown;
BOOLEAN MaintainHandleDatabase;
POOL_TYPE PoolType;
ULONG PagedPoolUsage;
ULONG NonPagedPoolUsage;
} OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION;

typedef struct _OBJECT_ALL_TYPES_INFORMATION {
ULONG NumberOfTypes;
OBJECT_TYPE_INFORMATION TypeInformation;
} OBJECT_ALL_TYPES_INFORMATION, *POBJECT_ALL_TYPES_INFORMATION;
*/

#define ntohs(s) /
  ( ( ((s) >> 8) & 0x00FF ) | /
( ((s) << 8) & 0xFF00 ) )

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;

typedef struct _SYSTEM_HANDLE_INFORMATION
{
    ULONG ProcessID;     //进程的标识ID
    UCHAR ObjectTypeNumber;     //对象类型
    UCHAR Flags;         //0x01 = PROTECT_FROM_CLOSE,0x02 = INHERIT
    USHORT Handle;         //对象句柄的数值
    PVOID Object;         //对象句柄所指的内核对象地址 WinNT4/Windows2000是0x1A xp中是0x1c 2003中是
    ACCESS_MASK GrantedAccess;     //创建句柄时所准许的对象的访问权
}SYSTEM_HANDLE_INFORMATION, * PSYSTEM_HANDLE_INFORMATION;

NTSYSAPI
NTSTATUS
NTAPI
ZwQuerySystemInformation(
  IN ULONG SystemInformationClass,
  IN OUT PVOID SystemInformation,
  IN ULONG SystemInformationLength,
  OUT PULONG ReturnLength);

NTSYSAPI
NTSTATUS
NTAPI
NtDeviceIoControlFile(
              IN HANDLE FileHandle,
              IN HANDLE Event OPTIONAL,
              IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
              IN PVOID ApcContext OPTIONAL,
              OUT PIO_STATUS_BLOCK IoStatusBlock,
              IN ULONG IoControlCode,
              IN PVOID InputBuffer OPTIONAL,
              IN ULONG InputBufferLength,
              OUT PVOID OutputBuffer OPTIONAL,
              IN ULONG OutputBufferLength
              );

NTSYSAPI
NTSTATUS
NTAPI
ZwQueryObject(
  IN HANDLE ObjectHandle,
  IN ULONG ObjectInformationClass,
  OUT PVOID ObjectInformation,
  IN ULONG ObjectInformationLength,
  OUT PULONG ReturnLength OPTIONAL
  );

NTSYSAPI
BOOLEAN
NTAPI
NtDuplicateObject(
IN HANDLE hSourceProcessHandle,
IN HANDLE hSourceHandle,
IN HANDLE hTargetProcessHandle,
OUT HANDLE * lpTargetHandle,
IN ULONG dwDesiredAccess,
IN BOOLEAN bInheritHandle,
IN ULONG dwOptions
);

NTSYSAPI
NTSTATUS
NTAPI
PsLookupProcessByProcessId(
  IN ULONG ulProcId,
  OUT PEPROCESS * pEProcess
  );


NTSTATUS
DriverEntry(IN PDRIVER_OBJECT DriverObject,
        IN PUNICODE_STRING RegistryPath);

void DriverUnload(IN PDRIVER_OBJECT DriverObject);

//几个全局变量,记录端口相关信息,最后列印出来
ULONG g_pid[1000];
ULONG g_port[1000];
ULONG g_handle[1000];
ULONG g_tcpudp[1000];
ULONG g_num =0 ;
ULONG g_tu[1000]; //g_tu=0 tcp, g_tu=1 udp

//获得所有句柄
ULONG GetHandleList()
{
  ULONG n;
  ULONG pBuffer;
  NTSTATUS status;
DbgPrint("GetHandleList/n");

  pBuffer =(ULONG)ExAllocatePool(PagedPool,0x1000);
  status = ZwQuerySystemInformation(SystemHandleInformation,(PVOID)pBuffer,0x1000,&n);
  ExFreePool((PVOID)pBuffer);
  if(STATUS_INFO_LENGTH_MISMATCH == status)
  {
    pBuffer =(ULONG)ExAllocatePool(NonPagedPool,n);
    ZwQuerySystemInformation(SystemHandleInformation,(PVOID)pBuffer,n,NULL);
    return pBuffer;
  }
  else
    return 0;
}

//根据句柄得到端口信息
void GetOpenPort(ULONG dwProcessesID,ULONG Handle,int NoCache,ULONG tcpudp)
{
  HANDLE hProc,DupHandle=NULL;
  USHORT openport;
  ULONG i=0;
  NTSTATUS status;
  TDI_CONNECTION_INFO   TdiConnInfo={0};
  TDI_CONNECTION_INFORMATION TdiConnInformation={0};
  ULONG dwRetu=0;  
  IO_STATUS_BLOCK   IoStatusBlock={0};
  CLIENT_ID id;
  OBJECT_ATTRIBUTES objatt = {0};
POBJECT_NAME_INFORMATION ObjectName;
char ObjectNameBuf[512];
// char ObjectNameMBS[261];
ULONG ReturnLen;
ObjectName = (POBJECT_NAME_INFORMATION)ObjectNameBuf;
ObjectName->Name.MaximumLength = 500;

  //DbgPrint("GetOpenPort/n");

  id.UniqueProcess = (HANDLE)dwProcessesID;
  id.UniqueThread = 0;
//打开对方进程
  NtOpenProcess(&hProc,PROCESS_DUP_HANDLE,&objatt,&id);
//复制句柄
  NtDuplicateObject(hProc,
    (HANDLE)Handle,
    (HANDLE)0xffffffff,
    &DupHandle,
    0,
    FALSE,
    2);
//根据object的数据得到端口信息
  if(NoCache==0x2)
  {
//取得句柄关联的对象的信息
ZwQueryObject(DupHandle, ObjectNameInformation, ObjectName, sizeof(ObjectNameBuf), &ReturnLen);

    TdiConnInformation.RemoteAddressLength= 4;
    status = NtDeviceIoControlFile((HANDLE)DupHandle,  
        NULL,
    NULL,
    NULL,
    &IoStatusBlock,
    0x210012, // Command code
    &TdiConnInformation,
    sizeof(TdiConnInformation),
    &TdiConnInfo,
    sizeof(TdiConnInfo));

    //进行TDI查询,得到连接的相关信息
    if(status == 0)
    {
        openport = ntohs((USHORT)TdiConnInfo.ReceivedTsdus);

        if(openport == 0)
          return;

        for(i=0;i         {
          if(g_pid == dwProcessesID && g_port == openport)
            if(tcpudp >= TCPUDP_FLAG && g_tcpudp >= TCPUDP_FLAG || tcpudp < TCPUDP_FLAG && g_tcpudp < TCPUDP_FLAG)
            return;
        }

        g_pid = dwProcessesID;
        g_port = openport;
        g_handle = Handle;
        g_tcpudp = tcpudp;
        g_num++;
  if (wcscmp(ObjectName->Name.Buffer, L"//Device//Tcp") == 0)
  {
  g_tu = 0;
  }
  if (wcscmp(ObjectName->Name.Buffer, L"//Device//Udp") == 0)
  {
  g_tu = 1;
  }
    }
  }
  if(NoCache==0x1)
  {
  ZwQueryObject(DupHandle, ObjectNameInformation, ObjectName, sizeof(ObjectNameBuf), &ReturnLen);

TdiConnInformation.RemoteAddressLength= 3;
    status = NtDeviceIoControlFile((HANDLE)DupHandle,    
    NULL,
    NULL,
    NULL,
    &IoStatusBlock,
    0x210012, // Command code
    &TdiConnInformation,
    sizeof(TdiConnInformation),
    &TdiConnInfo,
    sizeof(TdiConnInfo));              
    //进行TDI查询,得到连接的相关信息
      if(status == 0)
    {
        openport = ntohs((USHORT)TdiConnInfo.ReceivedTsdus);

        if(openport == 0)
          return;

        for(i=0;i         {
          if(g_pid == dwProcessesID && g_port == openport)
            if(tcpudp >= TCPUDP_FLAG && g_tcpudp >= TCPUDP_FLAG || tcpudp < TCPUDP_FLAG && g_tcpudp < TCPUDP_FLAG)
            return;
        }

        g_pid = dwProcessesID;
        g_port = openport;
        g_handle = Handle;
        g_tcpudp = tcpudp;
        g_num++;
  if (wcscmp(ObjectName->Name.Buffer, L"//Device//Tcp") == 0)
  {
  g_tu = 0;
  }
  if (wcscmp(ObjectName->Name.Buffer, L"//Device//Udp") == 0)
  {
  g_tu = 1;
  }
    }
  }
}

void Start(ULONG pBuffer)
{
  ULONG i;
//头4个字节是所有的句柄的数目UNONG 32位
//从第5个字节开始就是结构体了
  PSYSTEM_HANDLE_INFORMATION pProcesses = (PSYSTEM_HANDLE_INFORMATION)(pBuffer+4);
  ULONG nocache;
  ULONG tcpudp;
  PEPROCESS epro;
  char *p;
  ULONG uMajorVersion;
  ULONG uMinorVersion;
  ULONG uBuildNumber;
  ULONG uOsVer;

  DbgPrint("Start11/n");


PsGetVersion(&uMajorVersion, &uMinorVersion, &uBuildNumber, NULL);
if(uMajorVersion == 5)
{
if(uMinorVersion == 0)
{
  DbgPrint("2k/n");
  uOsVer = 0;//2k
}
else if(uMinorVersion == 1)
{
  uOsVer = 1;//xp
  DbgPrint("xp/n");
}
else if(uMinorVersion == 2)
{
  uOsVer = 2;//2k3
  DbgPrint("2k3/n");
}
else
{
  uOsVer = 3;//nt
  DbgPrint("NT/n");
}
}
else
{
uOsVer = 99;
DbgPrint("Unknow OS/n");
}

  for (i=0;i<((ULONG)(*(ULONG*)pBuffer));i++)
  {
//2000 xp 2003 三种操作系统
    if(pProcesses.ObjectTypeNumber == WIN2K_SOCKET_FLAG
  || pProcesses.ObjectTypeNumber == WINXP_SOCKET_FLAG
  || pProcesses.ObjectTypeNumber == WIN2K3_SOCKET_FLAG)
    {        
//得到SYSTEM_HANDLE_INFORMATION.object的相关数据
//这里要密切注意内存情况,一不小心就蓝屏。因为句柄经常变化,有些可能已经被销毁了
        nocache = (ULONG)pProcesses.Object;
        if(!MmIsAddressValid((VOID*)nocache))
          continue;
        nocache = (ULONG)(*((ULONG*)(nocache)+4));

        tcpudp = (ULONG)(*((ULONG*)(pProcesses.Object)+1));
        if(!MmIsAddressValid((VOID*)tcpudp))
          continue;
        tcpudp = (ULONG)(*((ULONG*)(tcpudp)+1));

        if(nocache == 2 || nocache == 1)
        {
          GetOpenPort(pProcesses.ProcessID,pProcesses.Handle,nocache,tcpudp);
        }
    }
  }

  for(i=0;i   {
//根据PID得到进程名
    PsLookupProcessByProcessId(g_pid,&epro);

if(uOsVer == 0)
{ //2k中进程名在EPROCESS结构中的位置
  p = (char*)epro + WIN2K_EPROCESS_NAMEOFFSET;
  //DbgPrint("2k/n");
}
if(uOsVer == 1)
{ //xp中进程名在EPROCESS结构中的位置
  p = (char*)epro + WINXP_EPROCESS_NAMEOFFSET;
  //DbgPrint("xp/n");
}
if(uOsVer == 2)
{ //2k3中进程名在EPROCESS结构中的位置
  p = (char*)epro + WIN2K3_EPROCESS_NAMEOFFSET;
  //DbgPrint("2k3/n");
}
if(uOsVer == 3)
{
  p = (char*)epro + WIN2K_EPROCESS_NAMEOFFSET; //NT
  //DbgPrint("nt/n");
}

if(uOsVer == 99)
{
  //DbgPrint("Unknow OS/n");
  break;
}

  if(g_tu == 0)
  DbgPrint("TCP:/tProcName=%s/tPID=%d/tport=%d/t%d/n",p,g_pid,g_port,g_tcpudp);
    if(g_tu == 1)
  DbgPrint("UDP:/tProcName=%s/tPID=%d/tport=%d/t%d/n",p,g_pid,g_port,g_tcpudp);
 
  }

  return;
}
//

NTSTATUS
DriverEntry(IN PDRIVER_OBJECT DriverObject,
        IN PUNICODE_STRING RegistryPath)
{
  ULONG pbuf;

  DbgPrint("DriverEntry/n");
 
  DriverObject->DriverUnload = DriverUnload;
 
  pbuf = GetHandleList();
  Start(pbuf);
 
  return STATUS_SUCCESS;
}


void DriverUnload(IN PDRIVER_OBJECT pDriverObject)
{
  NTSTATUS         status;
  //ResumeDestFunction();
  if(pDriverObject->DeviceObject != NULL)
{
IoDeleteDevice( pDriverObject->DeviceObject );
}

DbgPrint("DriverUnload/n");
}

参考文献:
1 Windows DDK
2 http://coffeeqiqi.blogchina.com
3 Leven-端口关联进程-在核心态的实现方法
4 Msdn
5 port/connection hiding   http://dev.csdn.net/Develop/article/28/84294.shtm
6 在NT系列操作系统里让自己“消失”
7 http://www.rootkit.com 

评论

#Blue_Dream_ 发表于2008-02-18 16:59:50  IP: 60.3.157.*

很多关于端口关联进程的方法都是在用户态实现的,如fport等,结合大虾们的方法,这里给出一种在核心态实现的方法,方法可能比较笨 ^_^
大概是
1.用ZwQuerySystemInformation列出系统所有的句柄
2.找出类型为SOCKET的句柄
3.根据SYSTEM_HANDLE_INFORMATION.object的一些数据,用NtDeviceIoControlFile得到端口相关信息

这种方法在用户态已经实现过了,正好是shotgun的方法加上isly的方法,这里主要是注意一些API的转换。
在WINDOWSXP下可以用,如果是2k,需要修改WINXP_SOCKET_FLAG和WINXP_EPROCESS_NAMEOFFSET,WINXP_SOCKET_FLAG是SOCKET句柄的类型值,2K下是0x1a,WINXP_EPROCESS_NAMEOFFSET是EPROCESS的进程名偏移值,2k下是0x1fc
# Blue_Dream_ 发表于2008-02-18 17:00:32  IP: 60.3.157.*
void Start(ULONG pBuffer)
{
ULONG i;
PSYSTEM_HANDLE_INFORMATION pProcesses = (PSYSTEM_HANDLE_INFORMATION)(pBuffer+4);
ULONG nocache;
ULONG tcpudp;
PEPROCESS epro;
char *p;

for (i=0;i<((ULONG)(*(ULONG*)pBuffer));i++)
{
if(pProcesses[i].ObjectTypeNumber == WINXP_SOCKET_FLAG)
{
//得到SYSTEM_HANDLE_INFORMATION.object的相关数据
//这里要密切注意内存情况,一不小心就蓝屏。因为句柄经常变化,有些可能已经被销毁了
nocache = (ULONG)pProcesses[i].Object;
if(!MmIsAddressValid((VOID*)nocache))
continue;
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值