哪些4399游戏盒下载HOOK了OpenProcess

扫一扫体验手机阅读
实现简单的ring3进程保护、hook OpenProcess函数、简单分析
<span type="1" blog_id="1361011" userid='
79篇文章,4W+人气,0粉丝
高并发架构之路
¥51.00134人订阅
9本网络安全实战书籍精华
¥51.00504人订阅
<span type="1" blog_id="1361011" userid='HookSSDT 通过HookOpenProcess函数阻止暴力枚举进程
首先要知道Ring3层调用OpenProcess的流程
//当Ring3调用OpenProcess //1从自己的模块(.exe)的导入表中取值
//2Ntdll.dll模块的导出表中执行ZwOpenProcess(取索引 进入Ring0层)
//3进入Ring0 从Ntoskernel.exe模块的导出表中执行ZwOpenProcess(取索引 获得SSDT服务地址)
//4通过索引在SSDT表中取值(NtOpenProcess的地址)
//5真正调用NtOpenProcess函数
我们可以通过在第4部通过索引将NtOpenProcess 换成 Base[索引] = FakeNtOpenP
1.我们要获取SSDT的结构信息
XP 32位的SSDT在Ntos模块导出表中有
//SSDT表的基地址32位(4Bytes)64位(8Bytes)
//XP 32位Ntos模块导出表中有
Win7 64 Ntos模块导出表中无
BOOLEAN GetSSDTAddressInWinXP_X86(ULONG32* SSDTAddress)
//从NtosKernel.exe 模块中的导出表获得该导出变量
KeServiceDescriptorTable
kd& dd KeServiceDescriptorTable
*SSDTAddress = NULL;
*SSDTAddress = (ULONG32)GetExportVariableAddressFormNtosExportTableByVariableName(L"KeServiceDescriptorTable");
if (*SSDTAddress!=NULL)
return TRUE;
return FALSE;
获取SSDT的地址32
win7 64位没有被导出 但可以通过读取制定的msr得出
// 来自 作者:胡文亮
Msr 的中文全称是就是&特别模块寄存器& (model specificregister) ,它控制 CPU 的工作环境和标示 CPU 的工作状态等信息(例如倍频、最大 TDP、危险警报温度) ,它能够读取,也能够写入,但是无论读取还是写入,都只能在 Ring 0 下进行。我们通过读取 C0000082 寄存器,能够得到 KiSystemCall64 的地址,然后从KiSystemCall64 的地址开始,往下搜索 0x500 字节左右(特征码是 4c8d15) ,就能得到KeServiceDescriptorTable 的地址了。同理,我们换一下特征码(4c8d1d) ,就能获得KeServiceDescriptorTableShadow 的地址了。
BOOLEAN GetSSDTAddressInWin7_X64(ULONG64* SSDTAddress)
kd& rdmsr c0000082
msr[c0000082] = fffff800`03ecf640
kd& u fffff800`03ecf640 l 50
nt!KiSystemCall64:
fffff800`03ecf640 0f01f8
fffff800`03ecf643 000000 mov
qword ptr gs:[10h],rsp
fffff800`03ecf64c a8010000 mov
rsp,qword ptr gs:[1A8h]
fffff800`03ecf655 6a2b
fffff800`03ecf657 65ff push
qword ptr gs:[10h]
fffff800`03ecf65f 4153
fffff800`03ecf661 6a33
fffff800`03ecf663 51
fffff800`03ecf664 498bca
fffff800`03ecf667 4883ec08
fffff800`03ecf66b 55
fffff800`03ecf66c 00
fffff800`03ecf673 488dac lea
rbp,[rsp+80h]
fffff800`03ecf67b 40
qword ptr [rbp+0C0h],rbx
fffff800`03ecf682 4889bdc8000000
qword ptr [rbp+0C8h],rdi
fffff800`03ecf689 0000
qword ptr [rbp+0D0h],rsi
fffff800`03ecf690 c645ab02
byte ptr [rbp-55h],2
fffff800`03ecf694 8010000 mov
rbx,qword ptr gs:[188h]
fffff800`03ecf69d 0f0d8bd8010000
prefetchw [rbx+1D8h]
fffff800`03ecf6a4 0fae5dac
stmxcsr dword ptr [rbp-54h]
fffff800`03ecf6a8 650fae ldmxcsr dword ptr gs:[180h]
fffff800`03ecf6b1 807b0300
byte ptr [rbx+3],0
fffff800`03ecf6b5 66c000 mov
word ptr [rbp+80h],0
fffff800`03ecf6be 0f848c000000
nt!KiSystemCall64+0x110 (fffff800`03ecf750)
fffff800`03ecf6c4
qword ptr [rbp-50h],rax
fffff800`03ecf6c8 48894db8
qword ptr [rbp-48h],rcx
fffff800`03ecf6cc
qword ptr [rbp-40h],rdx
fffff800`03ecf6d0 f6430303
byte ptr [rbx+3],3
fffff800`03ecf6d4 4c8945c8
qword ptr [rbp-38h],r8
fffff800`03ecf6d8 4c894dd0
qword ptr [rbp-30h],r9
fffff800`03ecf6dc 7405
nt!KiSystemCall64+0xa3 (fffff800`03ecf6e3)
fffff800`03ecf6de e80d140000
nt!KiSaveDebugRegisterState (fffff800`03ed0af0)
fffff800`03ecf6e3 f6430380
byte ptr [rbx+3],80h
fffff800`03ecf6e7 7442
nt!KiSystemCall64+0xeb (fffff800`03ecf72b)
fffff800`03ecf6e9 b
ecx,0C0000102h
fffff800`03ecf6ee 0f32
fffff800`03ecf6f0 48c1e220
fffff800`03ecf6f4 480bc2
fffff800`03ecf6f7 0000
qword ptr [rbx+0B8h],rax
fffff800`03ecf6fe 742b
nt!KiSystemCall64+0xeb (fffff800`03ecf72b)
fffff800`03ecf700 0000
qword ptr [rbx+1B0h],rax
fffff800`03ecf707 7422
nt!KiSystemCall64+0xeb (fffff800`03ecf72b)
fffff800`03ecf709 488b93b8010000
rdx,qword ptr [rbx+1B8h]
fffff800`03ecf710 0fba6b4c0b
dword ptr [rbx+4Ch],0Bh
fffff800`03ecf715 66ff8bc4010000
word ptr [rbx+1C4h]
fffff800`03ecf71c 00
qword ptr [rdx+80h],rax
fffff800`03ecf723 fb
fffff800`03ecf724 e
nt!KiUmsCallEntry (fffff800`03ed0240)
fffff800`03ecf729 eb0f
nt!KiSystemCall64+0xfa (fffff800`03ecf73a)
fffff800`03ecf72b f6430340
byte ptr [rbx+3],40h
fffff800`03ecf72f 7409
nt!KiSystemCall64+0xfa (fffff800`03ecf73a)
fffff800`03ecf731 f00fbaab lock bts dword ptr [rbx+100h],8
fffff800`03ecf73a 488b45b0
rax,qword ptr [rbp-50h]
fffff800`03ecf73e 488b4db8
rcx,qword ptr [rbp-48h]
fffff800`03ecf742 488b55c0
rdx,qword ptr [rbp-40h]
fffff800`03ecf746 4c8b45c8
r8,qword ptr [rbp-38h]
fffff800`03ecf74a 4c8b4dd0
r9,qword ptr [rbp-30h]
fffff800`03ecf74e 6690
fffff800`03ecf750 fb
fffff800`03ecf751 40
qword ptr [rbx+1E0h],rcx
fffff800`03ecf758
dword ptr [rbx+1F8h],eax
nt!KiSystemServiceStart:
fffff800`03ecf75e 0000
qword ptr [rbx+1D8h],rsp
fffff800`03ecf765 8bf8
fffff800`03ecf767 c1ef07
fffff800`03ecf76a 83e720
fffff800`03ecf76d 25ff0f0000
nt!KiSystemServiceRepeat:
fffff800`03ecf772 4c8d15c7202300
r10,[nt!KeServiceDescriptorTable (fffff800`)]
fffff800`03ecf772 +
= fffff800`
PUCHAR StartSearchAddress = (PUCHAR)__readmsr(0xC0000082);
//fffff800`03ecf640
PUCHAR EndSearchAddress = StartSearchAddress + 0x500;
PUCHAR i = NULL;
v1=,v2=,v3=;
iOffset = ;
ULONG64 VariableAddress = ;
*SSDTAddress = NULL;
for(i=StartSearchAi&EndSearchAi++)
) && MmIsAddressValid(i+) )
if(v1==0x4c && v2==0x8d && v3==0x15 )
memcpy(&iOffset,i+,);
*SSDTAddress = iOffset + (ULONG64)i + ;
if (*SSDTAddress==NULL)
return FALSE;
kd& dq fffff800`
fffff800`03ed0`
fffff800`00191 fffff800`03ed1f8c
return TRUE;
2从Ntdll模块中的导出表获得要Hook的函数索引
BOOLEAN GetSSDTFunctionIndexFromNtdllExportTableByFunctionNameInWinXP_X86(CHAR* szFindFunctionName,ULONG32* SSDTFunctionIndex)
0:001& u zwopenprocess
ntdll!ZwOpenProcess:
7c92d5e0 b87a000000
7c92d5e5 ba0003fe7f
edx,offset SharedUserData!SystemCallStub (7ffe0300)
7c92d5ea ff12
dword ptr [edx]
7c92d5ec c21000
7c92d5ef 90
ulOffset_SSDTFunctionIndex = ;
//从Ntdll模块的导出表中获得7c92d5e0
//使用内存映射将Ntdll模块映射到System进程的内存空间进行查找(Ntdll.dll模块的导出表中进行搜索)
bOk = FALSE;
wzFileFullPath[] = L"\\SystemRoot\\System32\\ntdll.dll";
MappingViewSize
MappingBaseAddress = NULL;
PIMAGE_NT_HEADERS
NtHeader = NULL;
PIMAGE_EXPORT_DIRECTORY ExportDirectory = NULL;
AddressOfFunctions
AddressOfNames
USHORT* AddressOfNameOrdinals = NULL;
szFunctionName
ULONG32 ulFunctionOrdinal
ULONG32 ulFunctionAddress
*SSDTFunctionIndex = -;
//将Ntdll.dll 当前的空间中
bOk = MappingPEFileInRing0Space(wzFileFullPath,&MappingBaseAddress, &MappingViewSize);
if (bOk==FALSE)
return FALSE;
NtHeader = RtlImageNtHeader(MappingBaseAddress);
if (NtHeader && NtHeader-&OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress)
ExportDirectory =(IMAGE_EXPORT_DIRECTORY*)((ULONG32)MappingBaseAddress + NtHeader-&OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
AddressOfFunctions = (ULONG32*)((ULONG32)MappingBaseAddress + ExportDirectory-&AddressOfFunctions);
AddressOfNames = (ULONG32*)((ULONG32)MappingBaseAddress + ExportDirectory-&AddressOfNames);
AddressOfNameOrdinals = (USHORT*)((ULONG32)MappingBaseAddress + ExportDirectory-&AddressOfNameOrdinals);
i & ExportDirectory-&NumberOfN i++)
szFunctionName = (char*)((ULONG32)MappingBaseAddress + AddressOfNames[i]);
//获得函数名称
ulFunctionOrdinal = AddressOfNameOrdinals[i];
ulFunctionAddress = (ULONG32)((ULONG32)MappingBaseAddress + AddressOfFunctions[ulFunctionOrdinal]);
*SSDTFunctionIndex = *(ULONG32*)(ulFunctionAddress+ulOffset_SSDTFunctionIndex);
}__except(EXCEPTION_EXECUTE_HANDLER)
ZwUnmapViewOfSection(NtCurrentProcess(), MappingBaseAddress);
return FALSE;
return TRUE;
获取函数索引32
BOOLEAN GetSSDTFunctionIndexFromNtdllExportTableByFunctionNameInWin7_X64(CHAR* szFindFunctionName,ULONG32* SSDTFunctionIndex)
0:004& u zwopenprocess
ntdll!NtOpenProcess:
ddc10 4c8bd1
ddc18 0f05
ddc1b 0f1f440000
dword ptr [rax+rax]
ulOffset_SSDTFunctionIndex = ;
bOk = FALSE;
wzFileFullPath[] = L"\\SystemRoot\\System32\\ntdll.dll";
MappingViewSize
MappingBaseAddress = NULL;
PIMAGE_NT_HEADERS
NtHeader = NULL;
PIMAGE_EXPORT_DIRECTORY ExportDirectory = NULL;
AddressOfFunctions
AddressOfNames
AddressOfNameOrdinals = NULL;
szFunctionName
ulFunctionOrdinal
ulFunctionAddress
*SSDTFunctionIndex = -;
//将Ntdll.dll 当前的空间中
bOk = MappingPEFileInRing0Space(wzFileFullPath,&MappingBaseAddress, &MappingViewSize);
if (bOk==FALSE)
return FALSE;
NtHeader = RtlImageNtHeader(MappingBaseAddress);
if (NtHeader && NtHeader-&OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress)
ExportDirectory =(IMAGE_EXPORT_DIRECTORY*)((ULONG64)MappingBaseAddress + NtHeader-&OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
AddressOfFunctions = (ULONG32*)((ULONG64)MappingBaseAddress + ExportDirectory-&AddressOfFunctions);
AddressOfNames = (ULONG32*)((ULONG64)MappingBaseAddress + ExportDirectory-&AddressOfNames);
AddressOfNameOrdinals = (USHORT*)((ULONG64)MappingBaseAddress + ExportDirectory-&AddressOfNameOrdinals);
i & ExportDirectory-&NumberOfN i++)
szFunctionName = (char*)((ULONG64)MappingBaseAddress + AddressOfNames[i]);
//获得函数名称
ulFunctionOrdinal = AddressOfNameOrdinals[i];
ulFunctionAddress = (ULONG64)((ULONG64)MappingBaseAddress + AddressOfFunctions[ulFunctionOrdinal]);
*SSDTFunctionIndex = *(ULONG32*)(ulFunctionAddress+ulOffset_SSDTFunctionIndex);
}__except(EXCEPTION_EXECUTE_HANDLER)
ZwUnmapViewOfSection(NtCurrentProcess(), MappingBaseAddress);
return FALSE;
return TRUE;
获取函数索引64
3.保存原先函数的地址
64位与32位不同 64为中存放的并不是SSDT函数的完整地址而是其相对于
ServiceTableBase[Index]&&4 的数据(称它为偏移地址)
4.在32位中换掉Base中索引里的数据 NtOpenProcess & &Base[索引] == FakeNtOpenProcess &--&HookSSDT
在32位中 直接替换就可以了但是......................
/* 一系列的说明 作者:胡文亮 */
HOOK SSDT 就很简单了,首先获得待 HOOK 函数的序号Index,然后通过公式把自己的代理函数的地址转化为偏移地址,然后把偏移地址的数据填入 ServiceTableBase[Index]。也许有些读者看到这里,已经觉得胜利在望了,我当时也是如此。但实际上我在这里栽了个大跟头,整整郁闷了很长时间!因为我低估了设计这套算法的工程师的智商,我没有考虑一个问题,为什么 WIN64 的 SSDT 表存放地址的形式这么奇怪?只存放偏移地址,而不存放完整地址?难道是为了节省内存?这肯定是不可能的,要知道现在内存白菜价。那么不是为了节省内存,唯一的可能性就是要给试图挂钩 SSDT 的人制造麻烦!要知道,WIN64 内核里每个驱动都 不在同一个 B 4GB 里,而 4 字节的整数只能表示 4GB的范围!所以无论你怎么修改这个值,都跳不出 ntoskrnl 的手掌心。如果你想通过修改这个值来跳转到你的代理函数, 那是绝对不可能的。 因为你的驱动的地址不 可能跟 l ntoskrnl 在同一个 B 4GB 里。然而,这位工程师也低估了我们中国人的智商, 在中国有两句成语, 这位工程师一定没听过, 叫 &明修栈道, 暗渡陈仓&以及&上有政策,下有对策& 。虽然不能直接用 4 字节来表示自己的代理函数所在的地址, 但是还是可以修改这个值的。 要知道, ntoskrnl 虽然有很多地方的代码通常是不会被执行的, 比如 KeBugCheckEx。 所以我的办法是: 修改这个偏移地址的值,使之跳转到 KeBugCheckEx ,然后在 x KeBugCheckEx 的头部写一个 2 12 字节的 mov - - jmp , 这是一个可以跨越 4GB B ! 的跳转, 跳到我们的函数里!
VOID HookSSDTWin7_X64(PULONG32 ServiceTableBase,ULONG32 ulSSDTFunctionIndex,ULONG64 ulFakeVariable)
//寻找一个内核不常用的函数(KeBugCheckEx) 进行InlineHook使其跳转到Fake_NtOpenProcess函数
ulVariable = ;
InlineHook(KeBugCheckEx,ulFakeVariable,szOldKeBugCheckExCode,);
//寻找一个内核不常用的函数(KeBugCheckEx) 计算SSDT中的偏移 进行置换
ulVariable = CalcFunctionOffsetInSSDT(KeBugCheckEx,);
ServiceTableBase[ulSSDTFunctionIndex] = (ULONG32)ulV
HookSSDT64
VOID HookSSDTWinXP_X86(PULONG32 ServiceTableBase,ULONG32 ulSSDTFunctionIndex,ULONG32 ulFakeVariable)
ServiceTableBase[ulSSDTFunctionIndex] = (ULONG32)ulFakeV
HookSSDT32
#ifndef CXX_HOOKSSDT_H
include "HookSSDT.h"
//1获得SSDT表的结构信息
//2从Ntdll模块中的导出表获得要Hook的函数索引
//3换掉Base中索引里的数据 NtOpenProcess
Base[索引] == FakeNtOpenProcess
---&HookSSDT
ServiceTableBase
SSDT_NtOpenProcessIndex
pfnNtOpenProcess
Old_NtOpenProcess
Old_NtOpenProcessOffset = ;
//针对Win7 x64
szOldKeBugCheckExCode[] = {};
DriverEntry(PDRIVER_OBJECT
DriverObject,PUNICODE_STRING RegisterPath)
#ifdef _WIN64
SSDTAddress = NULL;
ulVariable
szFindFunctionName[] = "ZwOpenProcess";
if (GetSSDTAddressInWin7_X64(&SSDTAddress)==FALSE)
return STATUS_UNSUCCESSFUL;
DbgPrint("Win7x64 SSDT:%p\r\n",SSDTAddress);
DbgPrint("Win7x64 SSDTBase:%p\r\n",((PSYSTEM_SERVICE_TABLE)SSDTAddress)-&ServiceTableBase);
kd& dd FFFFF l 200
fffff800`03e8b300
040d9a00 02f55c00 fff6ea00 02e87805
fffff800`03e8b310
031a4a06 bbf200
fffff800`03e8b320
dd00 02e7d100
fffff800`03e8b330
02f01 02dd00
fffff800`03e8b340
02df00 02ad0500 02cefe01
fffff800`03e8b350
02d01d02 02f01 0323ca01
fffff800`03e8b360
ed29c0 02b2e703 ffec1d00
fffff800`03e8b370
043c40 02c52c01 03126c00
fffff800`03e8b380
02d80 02ecfec0(NtOpenProcess Offset)
kd& u NtOpenProcess
nt!NtOpenProcess:
fffff800`0415d2ec 4883ec38
fffff800` 010000 mov
rax,qword ptr gs:[188h]
fffff800` 448a90f6010000
r10b,byte ptr [rax+1F6h]
fffff800`8542428
byte ptr [rsp+28h],r10b
fffff800`8542420
byte ptr [rsp+20h],r10b
fffff800`0415d30a e851fcffff
nt!PsOpenProcess (fffff800`0415cf60)
fffff800`83c438
//fffffec - FFFFF = 2D1FEC&&4 = 2D1FEC0
DbgPrint("Win7x64 SSDTNumberOfService:%d\r\n",((PSYSTEM_SERVICE_TABLE)SSDTAddress)-&NumberOfServices);
if (GetSSDTFunctionIndexFromNtdllExportTableByFunctionNameInWin7_X64(szFindFunctionName,&SSDT_NtOpenProcessIndex)==FALSE)
return STATUS_UNSUCCESSFUL;
DbgPrint("Win7x64 SSDT_NtOpenProcessIndex:%d\r\n",SSDT_NtOpenProcessIndex);
ServiceTableBase
= (PULONG32)((PSYSTEM_SERVICE_TABLE)SSDTAddress)-&ServiceTableB
Old_NtOpenProcessOffset
= (ULONG32)(ServiceTableBase[SSDT_NtOpenProcessIndex]);
ulVariable = Old_NtOpenProcessOffset&&;
Old_NtOpenProcess = (ULONG64)((PSYSTEM_SERVICE_TABLE)SSDTAddress)-&ServiceTableBase + ulV
DbgPrint("Win7x64 Old_NtOpenProcess:%p\r\n",ulVariable);
kd& u FFFFFEC
nt!NtOpenProcess:
fffff800`0415d2ec 4883ec38
fffff800` 010000 mov
rax,qword ptr gs:[188h]
fffff800` 448a90f6010000
r10b,byte ptr [rax+1F6h]
fffff800`8542428
byte ptr [rsp+28h],r10b
fffff800`8542420
byte ptr [rsp+20h],r10b
fffff800`0415d30a e851fcffff
nt!PsOpenProcess (fffff800`0415cf60)
fffff800`83c438
HookSSDTWin7_X64(ServiceTableBase,SSDT_NtOpenProcessIndex,(ULONG64)Fake_NtOpenProcess);
SSDTAddress
szFindFunctionName[] = "ZwOpenProcess";
if (GetSSDTAddressInWinXP_X86(&SSDTAddress)==FALSE)
return STATUS_UNSUCCESSFUL;
DbgPrint("WinXPx86 SSDT:%p\r\n",SSDTAddress);
DbgPrint("WinXPx86 SSDTBase:%p\r\n",((PSYSTEM_SERVICE_TABLE)SSDTAddress)-&ServiceTableBase);
kd& dd 804E58A0 l 200
80591bfb e1f35 805dbc47
805e1fbc 842e4b 80642e94
80650bbb 5e1787
586fa1 805e08e8
805dd45 805ee
804e5eb4 8cd537 804ed812
804eb7 8e1b65 80656cec
804e1d 5aa76b 8057dd2d
804e0c db662 805d6cd6
804ec31 d7e7f
804ecaa 805ba 805b1470
804ec7cd 56eb66
804ee56 98cb2 805a7ada
804eab552 fb07
804eddc8b 8d64ac
80642eef b6cd8
50bbb 80579e1c
e3f1 805cf473
805e36f2 80586ceb 8da3bb
805e9ab6 62f7e5 805723df
599bde 805e0d66 8058968d
805aad25 806349af 834bca
805aab94 805a9f96 805cf7e5 805cf944
805de058 805cece7 805cd5
805e804c 805eea8e 8062eee7
50ba7 805de2ef 805e318f
806220ab 73bfc
5ea252 8058270a(NtOpenProcess)
DbgPrint("WinXPx86 SSDTNumberOfService:%d\r\n",((PSYSTEM_SERVICE_TABLE)SSDTAddress)-&NumberOfServices);
if (GetSSDTFunctionIndexFromNtdllExportTableByFunctionNameInWinXP_X86(szFindFunctionName,&SSDT_NtOpenProcessIndex)==FALSE)
return STATUS_UNSUCCESSFUL;
DbgPrint("WinXPx86 SSDT_NtOpenProcessIndex:%d\r\n",SSDT_NtOpenProcessIndex);
//先保存原先的函数地址
ServiceTableBase
= (PULONG32)((PSYSTEM_SERVICE_TABLE)SSDTAddress)-&ServiceTableB
Old_NtOpenProcess
= (pfnNtOpenProcess)(ServiceTableBase[SSDT_NtOpenProcessIndex]);
DbgPrint("WinXPx86 Old_NtOpenProcess:%p\r\n",Old_NtOpenProcess);
kd& u 8058270A
nt!NtOpenProcess:
offset nt!ObWatchHandles+0x25c (804f52d8)
nt!_SEH_prolog (804e3e73)
dword ptr [ebp-2Ch],esi
edi,[ebp-28h]
dword ptr es:[edi]
HookSSDTWinXP_X86(ServiceTableBase,SSDT_NtOpenProcessIndex,(ULONG32)Fake_NtOpenProcess);
DriverObject-&DriverUnload = UnloadD
STATUS_SUCCESS;
//SSDT表的基地址32位(4Bytes)64位(8Bytes)
//XP 32位Ntos模块导出表中有
Win7 64 Ntos模块导出表中无
BOOLEAN GetSSDTAddressInWinXP_X86(ULONG32* SSDTAddress)
//从NtosKernel.exe 模块中的导出表获得该导出变量
KeServiceDescriptorTable
kd& dd KeServiceDescriptorTable
*SSDTAddress = NULL;
*SSDTAddress = (ULONG32)GetExportVariableAddressFormNtosExportTableByVariableName(L"KeServiceDescriptorTable");
if (*SSDTAddress!=NULL)
return TRUE;
return FALSE;
BOOLEAN GetSSDTFunctionIndexFromNtdllExportTableByFunctionNameInWinXP_X86(CHAR* szFindFunctionName,ULONG32* SSDTFunctionIndex)
0:001& u zwopenprocess
ntdll!ZwOpenProcess:
7c92d5e0 b87a000000
7c92d5e5 ba0003fe7f
edx,offset SharedUserData!SystemCallStub (7ffe0300)
7c92d5ea ff12
dword ptr [edx]
7c92d5ec c21000
7c92d5ef 90
ulOffset_SSDTFunctionIndex = ;
//从Ntdll模块的导出表中获得7c92d5e0
//使用内存映射将Ntdll模块映射到System进程的内存空间进行查找(Ntdll.dll模块的导出表中进行搜索)
bOk = FALSE;
wzFileFullPath[] = L"\\SystemRoot\\System32\\ntdll.dll";
MappingViewSize
MappingBaseAddress = NULL;
PIMAGE_NT_HEADERS
NtHeader = NULL;
PIMAGE_EXPORT_DIRECTORY ExportDirectory = NULL;
AddressOfFunctions
AddressOfNames
USHORT* AddressOfNameOrdinals = NULL;
szFunctionName
ULONG32 ulFunctionOrdinal
ULONG32 ulFunctionAddress
*SSDTFunctionIndex = -;
//将Ntdll.dll 当前的空间中
bOk = MappingPEFileInRing0Space(wzFileFullPath,&MappingBaseAddress, &MappingViewSize);
if (bOk==FALSE)
return FALSE;
NtHeader = RtlImageNtHeader(MappingBaseAddress);
if (NtHeader && NtHeader-&OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress)
ExportDirectory =(IMAGE_EXPORT_DIRECTORY*)((ULONG32)MappingBaseAddress + NtHeader-&OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
AddressOfFunctions = (ULONG32*)((ULONG32)MappingBaseAddress + ExportDirectory-&AddressOfFunctions);
AddressOfNames = (ULONG32*)((ULONG32)MappingBaseAddress + ExportDirectory-&AddressOfNames);
AddressOfNameOrdinals = (USHORT*)((ULONG32)MappingBaseAddress + ExportDirectory-&AddressOfNameOrdinals);
i & ExportDirectory-&NumberOfN i++)
szFunctionName = (char*)((ULONG32)MappingBaseAddress + AddressOfNames[i]);
//获得函数名称
ulFunctionOrdinal = AddressOfNameOrdinals[i];
ulFunctionAddress = (ULONG32)((ULONG32)MappingBaseAddress + AddressOfFunctions[ulFunctionOrdinal]);
*SSDTFunctionIndex = *(ULONG32*)(ulFunctionAddress+ulOffset_SSDTFunctionIndex);
}__except(EXCEPTION_EXECUTE_HANDLER)
ZwUnmapViewOfSection(NtCurrentProcess(), MappingBaseAddress);
return FALSE;
return TRUE;
BOOLEAN GetSSDTFunctionIndexFromNtdllExportTableByFunctionNameInWin7_X64(CHAR* szFindFunctionName,ULONG32* SSDTFunctionIndex)
0:004& u zwopenprocess
ntdll!NtOpenProcess:
ddc10 4c8bd1
ddc18 0f05
ddc1b 0f1f440000
dword ptr [rax+rax]
ulOffset_SSDTFunctionIndex = ;
bOk = FALSE;
wzFileFullPath[] = L"\\SystemRoot\\System32\\ntdll.dll";
MappingViewSize
MappingBaseAddress = NULL;
PIMAGE_NT_HEADERS
NtHeader = NULL;
PIMAGE_EXPORT_DIRECTORY ExportDirectory = NULL;
AddressOfFunctions
AddressOfNames
AddressOfNameOrdinals = NULL;
szFunctionName
ulFunctionOrdinal
ulFunctionAddress
*SSDTFunctionIndex = -;
//将Ntdll.dll 当前的空间中
bOk = MappingPEFileInRing0Space(wzFileFullPath,&MappingBaseAddress, &MappingViewSize);
if (bOk==FALSE)
return FALSE;
NtHeader = RtlImageNtHeader(MappingBaseAddress);
if (NtHeader && NtHeader-&OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress)
ExportDirectory =(IMAGE_EXPORT_DIRECTORY*)((ULONG64)MappingBaseAddress + NtHeader-&OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
AddressOfFunctions = (ULONG32*)((ULONG64)MappingBaseAddress + ExportDirectory-&AddressOfFunctions);
AddressOfNames = (ULONG32*)((ULONG64)MappingBaseAddress + ExportDirectory-&AddressOfNames);
AddressOfNameOrdinals = (USHORT*)((ULONG64)MappingBaseAddress + ExportDirectory-&AddressOfNameOrdinals);
i & ExportDirectory-&NumberOfN i++)
szFunctionName = (char*)((ULONG64)MappingBaseAddress + AddressOfNames[i]);
//获得函数名称
ulFunctionOrdinal = AddressOfNameOrdinals[i];
ulFunctionAddress = (ULONG64)((ULONG64)MappingBaseAddress + AddressOfFunctions[ulFunctionOrdinal]);
*SSDTFunctionIndex = *(ULONG32*)(ulFunctionAddress+ulOffset_SSDTFunctionIndex);
}__except(EXCEPTION_EXECUTE_HANDLER)
ZwUnmapViewOfSection(NtCurrentProcess(), MappingBaseAddress);
return FALSE;
return TRUE;
BOOLEAN GetSSDTAddressInWin7_X64(ULONG64* SSDTAddress)
kd& rdmsr c0000082
msr[c0000082] = fffff800`03ecf640
kd& u fffff800`03ecf640 l 50
nt!KiSystemCall64:
fffff800`03ecf640 0f01f8
fffff800`03ecf643 000000 mov
qword ptr gs:[10h],rsp
fffff800`03ecf64c a8010000 mov
rsp,qword ptr gs:[1A8h]
fffff800`03ecf655 6a2b
fffff800`03ecf657 65ff push
qword ptr gs:[10h]
fffff800`03ecf65f 4153
fffff800`03ecf661 6a33
fffff800`03ecf663 51
fffff800`03ecf664 498bca
fffff800`03ecf667 4883ec08
fffff800`03ecf66b 55
fffff800`03ecf66c 00
fffff800`03ecf673 488dac lea
rbp,[rsp+80h]
fffff800`03ecf67b 40
qword ptr [rbp+0C0h],rbx
fffff800`03ecf682 4889bdc8000000
qword ptr [rbp+0C8h],rdi
fffff800`03ecf689 0000
qword ptr [rbp+0D0h],rsi
fffff800`03ecf690 c645ab02
byte ptr [rbp-55h],2
fffff800`03ecf694 8010000 mov
rbx,qword ptr gs:[188h]
fffff800`03ecf69d 0f0d8bd8010000
prefetchw [rbx+1D8h]
fffff800`03ecf6a4 0fae5dac
stmxcsr dword ptr [rbp-54h]
fffff800`03ecf6a8 650fae ldmxcsr dword ptr gs:[180h]
fffff800`03ecf6b1 807b0300
byte ptr [rbx+3],0
fffff800`03ecf6b5 66c000 mov
word ptr [rbp+80h],0
fffff800`03ecf6be 0f848c000000
nt!KiSystemCall64+0x110 (fffff800`03ecf750)
fffff800`03ecf6c4
qword ptr [rbp-50h],rax
fffff800`03ecf6c8 48894db8
qword ptr [rbp-48h],rcx
fffff800`03ecf6cc
qword ptr [rbp-40h],rdx
fffff800`03ecf6d0 f6430303
byte ptr [rbx+3],3
fffff800`03ecf6d4 4c8945c8
qword ptr [rbp-38h],r8
fffff800`03ecf6d8 4c894dd0
qword ptr [rbp-30h],r9
fffff800`03ecf6dc 7405
nt!KiSystemCall64+0xa3 (fffff800`03ecf6e3)
fffff800`03ecf6de e80d140000
nt!KiSaveDebugRegisterState (fffff800`03ed0af0)
fffff800`03ecf6e3 f6430380
byte ptr [rbx+3],80h
fffff800`03ecf6e7 7442
nt!KiSystemCall64+0xeb (fffff800`03ecf72b)
fffff800`03ecf6e9 b
ecx,0C0000102h
fffff800`03ecf6ee 0f32
fffff800`03ecf6f0 48c1e220
fffff800`03ecf6f4 480bc2
fffff800`03ecf6f7 0000
qword ptr [rbx+0B8h],rax
fffff800`03ecf6fe 742b
nt!KiSystemCall64+0xeb (fffff800`03ecf72b)
fffff800`03ecf700 0000
qword ptr [rbx+1B0h],rax
fffff800`03ecf707 7422
nt!KiSystemCall64+0xeb (fffff800`03ecf72b)
fffff800`03ecf709 488b93b8010000
rdx,qword ptr [rbx+1B8h]
fffff800`03ecf710 0fba6b4c0b
dword ptr [rbx+4Ch],0Bh
fffff800`03ecf715 66ff8bc4010000
word ptr [rbx+1C4h]
fffff800`03ecf71c 00
qword ptr [rdx+80h],rax
fffff800`03ecf723 fb
fffff800`03ecf724 e
nt!KiUmsCallEntry (fffff800`03ed0240)
fffff800`03ecf729 eb0f
nt!KiSystemCall64+0xfa (fffff800`03ecf73a)
fffff800`03ecf72b f6430340
byte ptr [rbx+3],40h
fffff800`03ecf72f 7409
nt!KiSystemCall64+0xfa (fffff800`03ecf73a)
fffff800`03ecf731 f00fbaab lock bts dword ptr [rbx+100h],8
fffff800`03ecf73a 488b45b0
rax,qword ptr [rbp-50h]
fffff800`03ecf73e 488b4db8
rcx,qword ptr [rbp-48h]
fffff800`03ecf742 488b55c0
rdx,qword ptr [rbp-40h]
fffff800`03ecf746 4c8b45c8
r8,qword ptr [rbp-38h]
fffff800`03ecf74a 4c8b4dd0
r9,qword ptr [rbp-30h]
fffff800`03ecf74e 6690
fffff800`03ecf750 fb
fffff800`03ecf751 40
qword ptr [rbx+1E0h],rcx
fffff800`03ecf758
dword ptr [rbx+1F8h],eax
nt!KiSystemServiceStart:
fffff800`03ecf75e 0000
qword ptr [rbx+1D8h],rsp
fffff800`03ecf765 8bf8
fffff800`03ecf767 c1ef07
fffff800`03ecf76a 83e720
fffff800`03ecf76d 25ff0f0000
nt!KiSystemServiceRepeat:
fffff800`03ecf772 4c8d15c7202300
r10,[nt!KeServiceDescriptorTable (fffff800`)]
fffff800`03ecf772 +
= fffff800`
PUCHAR StartSearchAddress = (PUCHAR)__readmsr(0xC0000082);
//fffff800`03ecf640
PUCHAR EndSearchAddress = StartSearchAddress + 0x500;
PUCHAR i = NULL;
v1=,v2=,v3=;
iOffset = ;
ULONG64 VariableAddress = ;
*SSDTAddress = NULL;
for(i=StartSearchAi&EndSearchAi++)
) && MmIsAddressValid(i+) )
if(v1==0x4c && v2==0x8d && v3==0x15 )
memcpy(&iOffset,i+,);
*SSDTAddress = iOffset + (ULONG64)i + ;
if (*SSDTAddress==NULL)
return FALSE;
kd& dq fffff800`
fffff800`03ed0`
fffff800`00191 fffff800`03ed1f8c
return TRUE;
GetExportVariableAddressFormNtosExportTableByVariableName(WCHAR *wzVariableName)
UNICODE_STRING uniVariableN
PVOID VariableAddress = NULL;
RtlInitUnicodeString(&uniVariableName, wzVariableName);
//从Ntos模块的导出表中获得一个导出变量的地址
VariableAddress = MmGetSystemRoutineAddress(&uniVariableName);
return VariableA
UnloadDriver(PDRIVER_OBJECT DriverObject)
#ifdef _WIN64
UnHookSSDTWin7_X64(ServiceTableBase,SSDT_NtOpenProcessIndex,(ULONG32)Old_NtOpenProcessOffset);
UnHookSSDTWinXP_X86(ServiceTableBase,SSDT_NtOpenProcessIndex,(ULONG32)Old_NtOpenProcess);
VOID HookSSDTWin7_X64(PULONG32 ServiceTableBase,ULONG32 ulSSDTFunctionIndex,ULONG64 ulFakeVariable)
//寻找一个内核不常用的函数(KeBugCheckEx) 进行InlineHook使其跳转到Fake_NtOpenProcess函数
ulVariable = ;
InlineHook(KeBugCheckEx,ulFakeVariable,szOldKeBugCheckExCode,);
//寻找一个内核不常用的函数(KeBugCheckEx) 计算SSDT中的偏移 进行置换
ulVariable = CalcFunctionOffsetInSSDT(KeBugCheckEx,);
ServiceTableBase[ulSSDTFunctionIndex] = (ULONG32)ulV
VOID HookSSDTWinXP_X86(PULONG32 ServiceTableBase,ULONG32 ulSSDTFunctionIndex,ULONG32 ulFakeVariable)
ServiceTableBase[ulSSDTFunctionIndex] = (ULONG32)ulFakeV
UnHookSSDTWin7_X64(PULONG32 ServiceTableBase,ULONG32 ulSSDTFunctionIndex,ULONG32 ulOldVariable)
UnInlineHook(KeBugCheckEx,szOldKeBugCheckExCode,);
ServiceTableBase[ulSSDTFunctionIndex] = (ULONG32)ulOldV
UnHookSSDTWinXP_X86(PULONG32 ServiceTableBase,ULONG32 ulSSDTFunctionIndex,ULONG32 ulOldVariable)
ServiceTableBase[ulSSDTFunctionIndex] = (ULONG32)ulOldV
//将Ntdll.dll 模块映射到System.exe进程空间中
MappingPEFileInRing0Space(WCHAR* wzFileFullPath,OUT PVOID* MappingBaseAddress,PSIZE_T MappingViewSize)
UNICODE_STRING
uniFileFullP
OBJECT_ATTRIBUTES
IO_STATUS_BLOCK
hFile = NULL;
hSection = NULL;
if (!wzFileFullPath || !MappingBaseAddress){
return FALSE;
RtlInitUnicodeString(&uniFileFullPath, wzFileFullPath);
InitializeObjectAttributes(&oa,
&uniFileFullPath,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
//获得文件句柄
Status = IoCreateFile(&hFile,
GENERIC_READ | SYNCHRONIZE,
//文件绝对路径
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ,
FILE_OPEN,
FILE_SYNCHRONOUS_IO_NONALERT,
CreateFileTypeNone,
IO_NO_PARAMETER_CHECKING
if (!NT_SUCCESS(Status))
return FALSE;
oa.ObjectName = NULL;
Status = ZwCreateSection(&hSection,
SECTION_QUERY | SECTION_MAP_READ,
PAGE_WRITECOPY,
SEC_IMAGE,
指示内存对齐
ZwClose(hFile);
if (!NT_SUCCESS(Status))
return FALSE;
Status = ZwMapViewOfSection(hSection,
NtCurrentProcess(),
//映射到当前进程的内存空间中
MappingBaseAddress,
MappingViewSize,
ViewUnmap,
PAGE_WRITECOPY
ZwClose(hSection);
if (!NT_SUCCESS(Status))
return FALSE;
return TRUE;
VOID WPOFF()
//选择性编译,是给编译器看的
#if (defined(_M_AMD64) || defined(_M_IA64)) && !defined(_REALLY_GET_CALLERS_CALLER_)
_disable();
__writecr0(__readcr0() & (~(0x10000)));
EAX, NOT 10000H;
VOID WPON()
#if (defined(_M_AMD64) || defined(_M_IA64)) && !defined(_REALLY_GET_CALLERS_CALLER_)
__writecr0(__readcr0() ^ 0x10000);
_enable();
EAX, 10000H;
NTSTATUS Fake_NtOpenProcess(
PHANDLE ProcessHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,PCLIENT_ID ClientId)
EProcess = PsGetCurrentProcess();
//进程上下背景文
if (EProcess!=NULL)
//通过EProcess 获得进程名称
char *szProcessImageName = PsGetProcessImageFileName(EProcess);
return STATUS_ACCESS_DENIED;
Old_NtOpenProcess(ProcessHandle,DesiredAccess,ObjectAttributes,ClientId);
ULONG32 CalcFunctionOffsetInSSDT(ULONG64 ulFunctionAddress,ULONG32 ulParamCount)
kd& rdmsr c0000082
msr[c0000082] = fffff800`03edd640
kd&u fffff800`03edd640
fffff800`03edd751 40
qword ptr [rbx+1E0h],rcx
fffff800`03edd758
dword ptr [rbx+1F8h],eax
nt!KiSystemServiceStart:
fffff800`03edd75e 0000
qword ptr [rbx+1D8h],rsp
fffff800`03edd765 8bf8
fffff800`03edd767 c1ef07
fffff800`03edd76a 83e720
fffff800`03edd76d 25ff0f0000
nt!KiSystemServiceRepeat:
fffff800`03edd772 4c8d15c7202300
r10,[nt!KeServiceDescriptorTable (fffff800`)]
kd& dq fffff800`
fffff800`03edf300 00000
fffff800`00191 fffff800`03edff8c
fffff800`00`
fffff800`00`
kd& dd fffff800`03edf300
fffff800`03edf300
040d9a00 02f55c00 fff6ea00 02e87805
fffff800`03edf310
031a4a06 bbf200
fffff800`03edf300 + (02e87805&&4) = FFFFFA80
kd& u FFFFFA80
nt!NtReadFile:
fffff800`041c7a80 4c8bdc
fffff800`041c7a83 4d894b20
qword ptr [r11+20h],r9
fffff800`041c7a87 4d894318
qword ptr [r11+18h],r8
fffff800`041c7a8b
qword ptr [r11+10h],rdx
fffff800`041c7a8f 53
如果一个函数的参数个数小于等于4
ULONG32 ulVariable = ,i;
CHAR v1 = ;
szBits[] = {};
ulVariable = (ULONG32)(ulFunctionAddress-(ULONG64)ServiceTableBase);
ulVariable = ulVariable&&;
ulParamCount = ulParamCount-;
//NtReadFile
ulParamCount = ;
//处理低四位,填写参数个数
如果一个函数的参数为5 那么dwTemp的低4位就是 0001
如果参数是6 就是0002 因为 6要减4
#define SETBIT(x,y) x|=(1&&y)
//将X的第Y位置1
#define CLRBIT(x,y) x&=~(1&&y)
//将X的第Y位清0
#define GETBIT(x,y) (x & (1 && y))
//取X的第Y位,返回0或非0
//一个16进制 4个二进制
szBits[i]=GETBIT(ulParamCount,i);
if(szBits[i])
SETBIT(v1,i);
CLRBIT(v1,i);
ulParamCount
//把数据复制回去
memcpy(&ulVariable,&v1,);
return ulV
VOID InlineHook(ULONG64 ulOldVariable,ULONG64 ulFakeVariable,UCHAR* szOldCode,ULONG32 ulOldeCodeLength)
ulVariable = ;
UCHAR szNewCode[]="\xFF\x25\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF";
//InlineHook
ulVariable = ulFakeV
memcpy(szOldCode,(PVOID)ulOldVariable,ulOldeCodeLength);
memcpy(szNewCode+,&ulVariable,);
memset((PVOID)ulOldVariable,0x90,ulOldeCodeLength);
memcpy((PVOID)ulOldVariable,szNewCode,);
UnInlineHook(ULONG64 ulOldVariable,UCHAR* szOldCode,ULONG32 ulOldCodeLength)
memcpy((PVOID)ulOldVariable,szOldCode,ulOldCodeLength);
#ifndef CXX_HOOKSSDT_H
#define CXX_HOOKSSDT_H
#include &ntifs.h&
#include &ntimage.h&
#define SEC_IMAGE
//定义SSDT表的结构
typedef struct _SYSTEM_SERVICE_TABLE_X64{
ServiceTableB
ServiceCounterTableB
//SSDT表中的函数个数
ParamTableB
} SYSTEM_SERVICE_TABLE_X64, *PSYSTEM_SERVICE_TABLE_X64;
typedef struct _SYSTEM_SERVICE_TABLE_X86 {
ServiceTableB
ServiceCounterTableB
ULONG32 NumberOfS
//SSDT表中的函数个数
ParamTableB
} SYSTEM_SERVICE_TABLE_X86, *PSYSTEM_SERVICE_TABLE_X86;
#ifdef _WIN64
#define PSYSTEM_SERVICE_TABLE PSYSTEM_SERVICE_TABLE_X64
#define PSYSTEM_SERVICE_TABLE PSYSTEM_SERVICE_TABLE_X86
ServiceTableBase
[][][][][][][][]
char* PsGetProcessImageFileName(PEPROCESS EProcess);
PIMAGE_NT_HEADERS
RtlImageNtHeader(PVOID BaseAddress);
(*pfnNtOpenProcess)(
PHANDLE ProcessHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,PCLIENT_ID ClientId);
NTSTATUS Fake_NtOpenProcess(
PHANDLE ProcessHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,PCLIENT_ID ClientId);
UnloadDriver(PDRIVER_OBJECT DriverObject);
BOOLEAN GetSSDTAddressInWinXP_X86(ULONG32* SSDTAddress);
BOOLEAN GetSSDTFunctionIndexFromNtdllExportTableByFunctionNameInWinXP_X86(CHAR* szFindFunctionName,ULONG32* SSDTFunctionIndex);
BOOLEAN GetSSDTAddressInWin7_X64(ULONG64* SSDTAddress);
BOOLEAN GetSSDTFunctionIndexFromNtdllExportTableByFunctionNameInWin7_X64(CHAR* szFindFunctionName,ULONG32* SSDTFunctionIndex);
ULONG32 CalcFunctionOffsetInSSDT(ULONG64 ulFunctionAddress,ULONG32 ulParamCount);
InlineHook(ULONG64 ulOldVariable,ULONG64 ulFakeVariable,UCHAR* szOldCode,ULONG32 ulOldeCodeLength);
UnInlineHook(ULONG64 ulOldVariable,UCHAR* szOldCode,ULONG32 ulOldCodeLength);
PVOID GetExportVariableAddressFormNtosExportTableByVariableName(WCHAR *wzVariableName);
BOOLEAN MappingPEFileInRing0Space(WCHAR* wzFileFullPath,OUT PVOID* MappingBaseAddress,PSIZE_T MappingViewSize);
VOID WPOFF();
VOID WPON();
VOID HookSSDTWinXP_X86(PULONG32 ServiceTableBase,ULONG32 ulSSDTFunctionIndex,ULONG32 ulFakeVariable);
VOID HookSSDTWin7_X64(PULONG32 ServiceTableBase,ULONG32 ulSSDTFunctionIndex,ULONG64 ulFakeVariable);
VOID UnHookSSDTWinXP_X86(PULONG32 ServiceTableBase,ULONG32 ulSSDTFunctionIndex,ULONG32 ulOldVariable);
VOID UnHookSSDTWin7_X64(PULONG32 ServiceTableBase,ULONG32 ulSSDTFunctionIndex,ULONG32 ulOldVariable);
function addEvent(a, b, c, d) { a.addEventListener ? a.addEventListener(b, c, d) : a.attachEvent(&qu ...
VPS SSH账号是我们日常管理VPS的主要登入方式,尤其是Root账号,对Linux系统安全至关重要.以前好多站长喜欢用Putty中文版,这实际是别人修改官方Putty汉化而来,这些软件被植入了后门 ...
https://www.owasp.org/index.php/Session_Management_Cheat_Sheet#Session_ID_Properties 会话简介 HTTP是一种无状态 ...
参考资料 1)官方说明 支持 sorry,cena不支持rope 声明 1)头文件 #include&ext/rope& 2)调用命名空间 using namespace __gnu_cx ...
发现一个小点,先前没有注意的 stopPropagation: function() { var e = this.originalE ... if ( e.stopPropagation
PHP在linux上执行外部命令 一.PHP中调用外部命令介绍二.关于安全问题三.关于超时问题四.关于PHP运行linux环境中命令出现的问题 一.PHP中调用外部命令介绍在PHP中调用外部命令,可以 ...
欢迎大家指导与讨论 : ) 前言
Angular的作用域在本质上是分层次的(有的住户在低层, 有的住户在高层), 它们可以通过父子关系很自然地进行沟通.但通常, 这种沟通是单向的(父-&子的单 ...
黑字:认识 红字:要学 未添加:要学 ├─模拟├─字符串│
├─字符串基础│
├─manacher│
├─trie│
├─ac自动机│
├─后缀数组( ...
1.sdio接口层解析 SDIO总线 SDIO总线和USB总线类似,SDIO也有两端,其中一端是HOST端,另一端是device端.所有的通信都是由HOST端发送命令开始的,Device端只要能解析命 ...
一.数值类型 Mysql支持所有标准SQL中的数值类型,其中包括严格数据类型(INTEGER,SMALLINT,DECIMAL,NUMBERIC),以及近似数值数据类型(FLOAT,REAL,DOUB ...
一.在windows平台上安装GNU环境 windows操作系统不自带GNU环境,如果需要开发跨平台的C语言程序,那么需要给windows安装GNU环境 windows下的两款GNU环境:MinGW和 ...
和R自带的绘图系统不同,ggplot2不能直接通过par(mfrow) 或者 layout()来排版多张图片.终于发现,其实可以通过一个『gridExtra』包来搞定: require(gridExt ...
这是一篇非常详细和精彩的介绍MAPI over HTTP协议英文博文.原文地址如下: http://blogs.technet.com/b/exchange/archive//ou ...
文本解析: 将txt存入DataFile,DataFile包含DataNode,每个DataNode是txt中的一行,每个DataNode包含若干token(std::vector&string ...
修改maven 的setting.xml &mirror& &id&nexus-aliyun&/id& &mirrorOf&*&/mirrorOf ...
TRUNC(SYSDATE)即可默认当前日期(年月日),TRUNC(SYSDATE,'yyyy-mm-dd'),精度说明符过多
一:运行给定的案例 1.获取jar包里的方法 2.运行hbase自带的mapreduce程序 lib/hbase-server-0.98.6-hadoop2.jar 3.具体运行 4.运行一个小方法
事务处理是在数据处理时经常遇到的问题,经常用到的方法有以下三种总结整理如下:方法1:直接写入到sql 中在存储过程中使用 BEGIN TRANS, COMMIT TRANS, ROLLBACK TRA ...
主要是因为json_encode格式的数据,中间带有\,在存入数据库的时候,会把反斜杠删除了. 所以,想要存进去的话,需要在外层调用一下函数addslashes();这个函数会在每个反斜杠的前面添加反 ...

我要回帖

更多关于 爱吾游戏宝盒 的文章

 

随机推荐