Rootkit之HOOK小结
目前接触的HOOK总结,学习HOOK只是为了让我对内核更加熟悉,我对那些毛的病毒木马没毛兴趣。
Windows平台上HOOK:
应用层HOOK:
1.消息HOOK:局部钩子、全局钩子、全局低级键盘钩子之类
2.IAT HOOK:通过修改IAT(导入表)表中的地址
过程就是先取DOS头,再取PE头偏移,再获取导入信息,其中的FirstThunk就是IAT偏移,再遍历,这样就找到了IAT表
3.EAT HOOK:(这个没有实际去做,知道思路)
详见http://bbs.pediy.com/showthread.php?t=62574
内核级HOOK:
内核hook基本上大同小异,都是获取相关函数的地址后修改成自己函数的地址
1.IDT HOOK:通过修改IDT表中的ISR例程地址
#pragma pack(push) #pragma pack(1) // 1字节对齐 typedef struct _IDTR //IDT基址 { USHORT limit; //范围占位 ULONG base; //基地址占位_IDT_ENTRY类型指针 }IDTR,*PIDTR; typedef struct _IDT_ENTRY { USHORT offset_low; //中断处理函数地址低位 USHORT selector; UCHAR reserved; UCHAR type:4; //4位 UCHAR always0:1; //1位 UCHAR dpl:2; //2位 UCHAR present:1;//1位 USHORT offset_high;//中断处理函数地址低位 }IDT_ENTRY,*PIDT_ENTRY;//获取基址实际上是这个类型 #pragma pack(pop) //#pragma pack(pop)
IDT 详解
http://blog.csdn.net/fwqcuc/article/details/5855460
http://blog.csdn.net/fwqcuc/article/details/5855715
IDT 多核检测
http://hi.baidu.com/andriy_aolala/blog/item/e841c1cd72277f5b0eb34510.html
2.SSDT HOOK:通过修改SSDT表中函数地址
系统服务描述符表 在ntoskrnl.exe导出KeServiceDescriptorTable 这个表
typedef struct _ServiceDescriptorTable { PVOID ServiceTableBase; //System Service Dispatch Table 的基地址 PVOID ServiceCounterTable; //包含着 SSDT 中每个服务被调用次数的计数器。这个计数器一般由sysenter 更新。 unsigned int NumberOfServices;//由 ServiceTableBase 描述的服务的数目。 PVOID ParamTableBase; //包含每个系统服务参数字节数表的基地址-系统服务参数表 }*PServiceDescriptorTable; //由SSDT索引号获取当前函数地址 //NtOpenProcess [[KeServiceDescriptorTable]+0x7A*4] extern PServiceDescriptorTable KeServiceDescriptorTable;
3.Inline HOOK:通过修改ntoskrnl导出Nt函数的字节,加入JMP
像如果u nt!NtOpenProcess函数,JMP需要5字节,选择合适的地方插入JMP到自己定义的函数即可
4.Shadow SSDT HOOK
正常情况下,ETHREAD中的ServiceTable,要么指向KeServiceDescriptorTable,要么指向KeServiceDescriptorTableShadow,注意这句话啊
ETHREAD->ServiceTable从来不会直接接向GUI的那张表,而是指向整体的KeServiceDescriptorTableShadow,用windbg观察就知道了
系统中既有KeServiceDescriptorTable也有KeServiceDescriptorTableShadow,他们各司其职,非GUI线程使用KeServiceDescriptorTable,GUI线程使用KeServiceDescriptorTableShadow,这是Windows的设计。非GUI线程如果要调用GUI服务就会用PsConvertToGuiThread把ETHREAD->ServiceTable切换为KeServiceDescriptorTableShadow,而GUI线程调用普通的Win32服务时并不需要切换,因为KeServiceDescriptorTableShadow中已经有个这张表,所以KeServiceDescriptorTableShadow可以看成是KeServiceDescriptorTable的增强版
KeServiceDescriptorTable中第二张表之所以无效,是因为非GUI线程根本不需要这张表,所以没有填充
#pragma PAGECODE DWORD Get_KeServiceDescriptorTableShadow_Addr() { DWORD KeServiceDescriptorTableShadow=0; DWORD Version=GetVersion(); switch (Version ) { case VERSION_2K: KeServiceDescriptorTableShadow=(DWORD)KeServiceDescriptorTable+0xE0; break; case VERSION_2K3: break; case VERSION_XP: KeServiceDescriptorTableShadow=(DWORD)KeServiceDescriptorTable-0x40;//XP系统的影子描述表是-0X40 break; default: break; } return KeServiceDescriptorTableShadow; }
链接:
http://bbs.pediy.com/showthread.php?t=56955
http://bbs.pediy.com/showthread.php?t=65931
http://bbs.pediy.com/showthread.php?t=82066
http://bbs.pediy.com/showthread.php?t=98909
5.IRP HOOK
1) 可用办法之一:hook IofCallDriver实现irp 拦截。
2) 可用办法之二:写一个过滤驱动,挂在你要hook其irp的那个驱动之上。
3) 可用办法之三:直接修改你要hook其irp的那个驱动的MajorFunction函数表。
http://bbs.pediy.com/showthread.php?t=60022
http://bbs.pediy.com/showthread.php?t=111559
http://bbs.pediy.com/showthread.php?t=96245
http://bbs.pediy.com/showthread.php?t=97821
6.Object HOOK
当你调用NtCreateFile->IoCreateFile->ObOpenObjectByName->ObpLookupObjectName->IopParseFile->IopParseDevice
IopParseFile最终也会调用IopParseDevice
ObjectHook其实就是比如你要HOOK 创建打开就是OBJECT_TYPE_INITIALIZER->ParseProcedure
http://bbs.pediy.com/showthread.php?t=128161
http://bbs.pediy.com/showthread.php?t=134415
http://www.xfocus.net/articles/200802/966.html
http://forum.eviloctal.com/thread-33688-1-1.html
7.sysenter HOOK
通过修改MSR寄存器的值来达到hook的目的,一般的拦截方法就是通过rdmsr wrmsr 两个指令把原来的sysenter地址改成自己的sysenter地址来实现的
NTSTATUS DriverEntry( IN PDRIVER_OBJECT theDriverObject, IN PUNICODE_STRING theRegistryPath ) { theDriverObject->DriverUnload = OnUnload; __asm { mov ecx, 0x176 rdmsr // read the value of the IA32_SYSENTER_EIP register mov d_origKiFastCallEntry, eax mov eax, MyKiFastCallEntry // Hook function address wrmsr // Write to the IA32_SYSENTER_EIP register } return STATUS_SUCCESS; }
http://bbs.pediy.com/showthread.php?t=60247
http://bbs.pediy.com/showthread.php?t=42705
几个学习链接:
http://bbs.pediy.com/showthread.php?t=81204
http://bbs.pediy.com/showthread.php?t=40832
http://bbs.pediy.com/showthread.php?t=142142
http://bbs.pediy.com/showthread.php?t=131397
http://bbs.pediy.com/showthread.php?t=98493
http://bbs.pediy.com/showthread.php?t=138620
Detours:Binary Interception of Win32 Functions
Load Your 32-bit DLL into Another Process's Address Space Using INJLIB
http://blog.csdn.net/coding_hello
http://www.cnblogs.com/me-sa/articles/671862.html
Hide your ssdt hook http://hi.baidu.com/sagittar_4d5a/blog/item/fe735660546f3143ebf8f8df.html
Linux平台上的HOOK:
很多Windows上的HOOK,Linux都可以做。
例如sys_call_table,还有IDT等等
在linux下主要的还是netfilter中的HOOK,这个才是Linux的重点。
包横穿netfilter系统示意图:
------ →[1]------ →[route]------ →[3]------ →[4]------ →
| ^
| |
| [route]
v |
[2] [5]
| ^
| |
v |
[1]:nf_ip_pre_routing:刚刚进入网络层的数据包通过此点(刚刚进行完版本号,校验和等检测), 源地址转换在此点进行;
[2]:nf_ip_local_in:经路由查找后,送往本机的通过此检查点,input包过滤在此点进行;
[3]:nf_ip_forward:要转发的包通过此检测点,forword包过滤在此点进行;
[4]:nf_ip_post_routing:所有马上便要通过网络设备出去的包通过此检测点,内置的目的地址转换功能(包括地址伪装)在此点进行;
[5]:nf_ip_local_out:本机进程发出的包通过此检测点,output包过滤在此点进行。
Linux下gdb检测rootkit:
http://os.51cto.com/art/201001/178676.htm
http://linkboy.blog.51cto.com/821152/297549