rootkit逃过杀软检测
作者:Trojan [ESST]
信息来源: 噩靈戰隊[Evil-Soul Security Team] http://bbs.x-xox-x.com/
2009年写的
有一个时期,杀毒软件的内核部分常常是用PsSetCreateProcessNotify为基础,进行安全检查.比如有一个进程诞生的时候,检查是否是已知的病毒进程,所以在加载dll的时候检查里面有没有病毒码.刚才提到的PsSetCreateProcessNotify这个函数原型如下:
NTSTATUS
PsSetCreateProcessNotifyRoutine(
IN PCREATE_PROCESS_NOTIFY_ROUTINE NotifyRoutine,
IN BOLLEAN Remove
);
其中NotifyRoutine是一个回调函数.我们假设Remove为FLASE,则执行这个函数的结果是把NofifyRountine注册了一个回调函数.原型如下:
VOID
(*PCREATE_PROCESS_NOTIFY_ROUTINE)(
IN HANDLE ParentId,
IN HANDLE ProcessId,
IN BOOLEAN Create
);
这个函数被回调的时候,ParentId是父进程Id,而ProcessId则是系统要通知我们的进程ID,这个进程被创建或者被注销的时候,这个函数被调用.
大家可能会问,只得到进程ID,如何检查这个进程,比如EXE文件路径怎么获得?命令行参数怎么获得?在WDK之前,这些都可以通过一些非公开的技术手段来获得.但在WDK之后,如果使用PsSetCreateProcessNotifyRoutineEx,可以比较容易得到这些参数.
PsSetCreateProcessNotifyRoutineEx的不同之处在与回调函数的参数发生了改变:
VOID
CreateProcessNotifyEx (
__inout PEPROCESS Process,
__in HANDLE ProcessId,
__in_opt PPS_CREATE_NOTIFY_INFO CreateInfo
);
当CreateInfor不为空的时候,这些信息被提供在CreateInfo中.结构如下:
typedef struct _PS_CREATE_NOTIFY_INFO {
__in SIZE_T Size;
union {
__in ULONG Flags;
struct {
__in ULONG FileOpenNameAvailable : 1;
__in ULONG Reserved : 31;
};
};
__in HANDLE ParentProcessId;
__in CLIENT_ID CreatingThreadId;
__inout struct _FILE_OBJECT *FileObject;
__in PCUNICODE_STRING ImageFileName;
__in_opt PCUNICODE_STRING CommandLine;
__out NTSTATUS CreationStatus;
} PS_CREATE_NOTIFY_INFO, *PPS_CREATE-NOTIFY_INFO;
既然如此,作为杀软的开发者,就可以在进程加载的时候,检查ImageFileName,或者直接得到FileObject来扫描其中是否含有病毒特征码.
此外进程加载的每个DLL也需要检查.这有另一个函数提供
NTSTATUS
PsSetLoadImageNotifyRoutine(
IN PLOAD_IMAGE_NOTIFY_ROUTINE NotifyRountine
);
这个函数也追加一个回调函数,当有dll模块被进程加载的时候,这个回调函数会被系统调用.这样dll加载的时候.杀软的开发者可以从FullImageName中得到dll文件的名字,可以预先对这个文件进行扫描.
如果rootkit打算防止杀软用以上的方法扫描一些隐秘的进程或者模块文件.Hook上面两个函数是一个可行的途径.但是呢,很多杀软都会配备HIPS都会关注被HOOK的内核调用.那么就不能HOOK拉.下面我用winDbg跟踪到vista32位版本中PsSetCteateProcessNotifyRoutine的实现过程.
kd> u PsSetCreateProcessNotifyRoutine nt!PsSetCreateProcessNotifyRoutine; 81a1c9f3 8bff mov edi,edi 81a1c9f5 55 push ebp 81a1c9f6 8bec mov ebp,esp 81a1c9f8 5d pop ebp 81a1c9f9 eb0a jmp nt!PspSetCreateProcessNotifyRoutine (81a1ca05) 81a1c9fb cc int 3 81a1c9fc cc int 3 81a1c9fd cc int 3
很明显,这个PsSetCreateProcessNotifyRoutine不是要领.因为直接跳转PspSetCreateProcessNotifyRoutine去了.在看看PspSetCreateProcessNotifyRoutine的跟踪;
nt!PspSetCreateProcessNotifyRoutine: 81a1ca05 8bff mov edi,edi 81a1ca07 55 push ebp 81a1ca08 8bec mov ebp,esp 81a1ca0a 51 push ecx ;这里研究下[ebp+0ch]到底是哪几个参数 ;回忆下函数原型 NTSTATUS ;PsSetCreateProcessNotifyRoutine( ; IN PCREATE_PROCESS_NOTIFY_ROUTINE NotifyRoutine, ; IN BOLLEAN Remove ;先压入的是remove然后压入NotifyRoutine,最后压入返回地址.然后跳转到 ;PsSetCreateProcessNotifyRoutine此时remove实际上是esp+8h. ;进入PsSetCreateProcessNotifyRoutine后连续Push和pop刚好平衡.esp ;没有变在跳转PspSetCreateProcessNotifyRoutine此时出现push ebp, ;remove应该是[ebp+8h+4h]也就是[ebp+0ch].所以[ebp+08h]是第一个 ;参数 81a1ca0b 807d0c00 cmp byte prt [ebp+0ch],0 81a1ca0f 53 push ebx 81a1ca10 56 push esi 81a1ca11 57 push edi ;如果remove为false跳转,否则继续 81a1ca12 7474 je nt!PspSetCreateProcessNotifyRoutine+0x83 (81a1ca88) ;这里开始移除回调函数 ;;省略部分 ;最后判断PspNotifyEnableMask的第二位是否为0.如果不为0则跳转 ;返回成功
上面省略了一大部分,其实当你研究完这个函数构成就可以把别人的注册的回调函数去掉.就是如果知道别人的注册过的回调函数指针.就可以去掉他.对于rootkit,如果remove掉了这些回调函数.杀毒软件可以被悄无声息的禁用掉.还不会出错.很基本的文章.本人刚接触内核.参考了很多东西.写了本文.有什么错误,欢迎大家指证.
没有评论 »
还没有评论呢。
这篇文章上的评论的 RSS feed TrackBack URI
留下评论
If you want to leave a feedback to this post or to some other user´s comment, simply fill out the form below.