再谈进程与端口的映射
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:
评论加载中...
|
上一篇: 网页木马深度剖析以及手工清除
下一篇: ASP网站漏洞解析及黑客入侵防范方法