内核级利用通用Hook函数方法检测进程
来源:互联网 发布:免费朗读软件 编辑:程序博客网 时间:2024/05/01 14:26
www.hackbase.com 2007-1-5 0 黑客基地
介绍通用hook的一点思想:
在系统内核级中,ms的很多信息都没公开,包括函数的参数数目,每个参数的类型等。在系统内核中,访问了大量的寄存器,而很多寄存器的值,是上层调用者提供的。如果值改变系统就会变得不稳定。很可能出现不可想象的后果。另外有时候对需要hook的函数的参数不了解,所以不能随便就去改变它的堆栈,如果不小心也有可能导致蓝屏。所以hook的最佳原则是在自己的hook函数中呼叫原函数的时候,所有的寄存器值,堆栈里面的值和hook前的信息一样。这样就能保证在原函数中不会出错。一般我们自己的hook的函数都是写在c文件里面的。例如hook的目标函数kireadythread。
那么一般就自己实现一个:
mykireadythread(...) { ...... call kireadythread ...... }
但是用c编译器编译出来的代码会出现一个堆栈帧:
push ebp mov ebp,esp
这就和我们的初衷不改变寄存器的数违背了,所以我们可以自己用汇编来实现mykireadythread。
_func@0 proc pushad ;保存通用寄存器 call _cfunc@0 ;这里是在进入原来函数前进行的一些处理。 popad ;恢复通用寄存器 push eax mov eax,[esp+4] ;得到系统在call 目标函数时入栈的返回地址。 mov ds:_orgret,eax ;保存在一个临时变量中 pop eax mov [esp],retaddr ;把目标函数的返回地址改成自己的代码空间的返回地址,使其返回 后能接手继续的处理 jmp _orgdestfunction ;跳到原目标函数中 retaddr: pushad ;原函数处理完后保存寄存器 call _hookdestfunction@0 ;再处理 popad ;回复寄存器 jmp ds:_orgret ;跳到系统调用目标函数的下一条指令。 _func@0 endp
当我们要拦截目标api的时候,只要修改原函数头5个字节的机器为一个jmp_func就行了。然后把原来的5字节保存,在跳入原函数时,恢复那5个字节即可。
hook kireadythread检测系统中的进程:
在线程调度抢占的的时候会调用kireadythread,它的原型为void fastcall kireadythread (in prkthread thread),在进入kireadythread时,ecx指向thread。所以完全可以hook kireadythread 然后用ecx的值得到但前线程的进程信息。kireadythread没被ntosknrl.exe导出,所以通过硬编码来。在2000sp4中地址为0x8043141f。
具体实现:
//////////////////////////////// // 1.cpp //////////////////////////////// #ifdef __cplusplus extern "c" { #endif #include "ntddk.h" #include "string.h" #include "ntifs.h" #include "stdio.h" #define file_device_event 0x8000 #define ioctl_passbuf / ctl_code(file_device_event, 0x802, method_buffered, file_any_access) void driverunload (in pdriver_object pdriverobject); ntstatus driverentry(in pdriver_object driverobject, in punicode_string registrypath); void cfunc (); void hookdestfunction(); ntstatus deviceiocontroldispatch(in pdevice_object deviceobject, in pirp pirp); extern void func(); void resumedestfunction(); const wchar devlink[] = l"//??//myevent"; const wchar devname[] = l"//device//myevent"; unicode_string devnameunicd; unicode_string devlinkunicd; ulong orgdestfunction = (ulong)0x8043141f; //kireadythread char jmpmycode [] = {0xe9,0x00,0x00,0x00,0x00}; char orgcode [5]; char outbuf[128][16]; int count = 0; ulong orgcr0; #ifdef __cplusplus } #endif void disablewriteprotect( pulong poldattr) { ulong uattr; _asm { push eax; mov eax, cr0; mov uattr, eax; and eax, 0fffeffffh; // cr0 16 bit = 0 mov cr0, eax; pop eax; }; *poldattr = uattr; //保存原有的 cro 属性 } void enablewriteprotect( ulong uoldattr ) { _asm { push eax; mov eax, uoldattr; //恢复原有 cr0 属性 mov cr0, eax; pop eax; }; } ntstatus driverentry(in pdriver_object pdriverobject, in punicode_string registrypath) { ntstatus status; pdevice_object pdevice; dbgprint("driverentry called!/n"); rtlinitunicodestring (&devnameunicd, devname ); rtlinitunicodestring (&devlinkunicd, devlink ); status = iocreatedevice ( pdriverobject, 0, &devnameunicd, file_device_unknown, 0, true, &pdevice ); if( !nt_success(status)) { dbgprint(("can not create device./n")); return status; } status = iocreatesymboliclink (&devlinkunicd, &devnameunicd); if( !nt_success(status)) { dbgprint(("cannot create link./n")); return status; } pdriverobject->driverunload = driverunload; pdriverobject->majorfunction[irp_mj_create] = pdriverobject->majorfunction[irp_mj_close] = pdriverobject->majorfunction[irp_mj_device_control] = deviceiocontroldispatch; pdriverobject->driverunload = driverunload; * ( (ulong*) (jmpmycode+1) ) = (ulong)func - (ulong)orgdestfunction - 5; memcpy(orgcode,(char*)orgdestfunction,5); hookdestfunction(); return status_success; } void driverunload (in pdriver_object pdriverobject) { ntstatus status; resumedestfunction(); if(pdriverobject->deviceobject != null) { status=iodeletesymboliclink( &devlinkunicd ); if ( !nt_success( status ) ) { dbgprint(( "iodeletesymboliclink() failed/n" )); } iodeletedevice( pdriverobject->deviceobject ); } } void displayname(pkthread thread) { pkprocess process = thread->apcstate.process; peprocess peprocess = (peprocess)process; dbgprint("imagefilename = %s /n",peprocess->imagefilename); sprintf(outbuf[count++],"%s",peprocess->imagefilename); } void cfunc (void) { ulong pkheader=0; __asm { mov pkheader,ecx //ecx寄存器是kireadythread中的prkthread参数 } resumedestfunction(); if ( pkheader != 0 && count < 128 ) { displayname((pkthread)pkheader); } } void hookdestfunction() { disablewriteprotect(&orgcr0); memcpy((char*)orgdestfunction,jmpmycode,5); enablewriteprotect(orgcr0); } void resumedestfunction() { disablewriteprotect(&orgcr0); memcpy((char*)orgdestfunction,orgcode,5); enablewriteprotect(orgcr0); } ntstatus deviceiocontroldispatch( in pdevice_object deviceobject, in pirp pirp ) { pio_stack_location irpstack; ntstatus status; pvoid inputbuffer; ulong inputlength; pvoid outputbuffer; ulong outputlength; object_handle_information objhandleinfo; status = status_success; // 取出ioctl请求代码 irpstack = iogetcurrentirpstacklocation(pirp); switch (irpstack->majorfunction) { case irp_mj_create : dbgprint("call irp_mj_create/n"); break; case irp_mj_close: dbgprint("call irp_mj_close/n"); break; case irp_mj_device_control: dbgprint("irp_mj_device_control/n"); inputlength=irpstack->parameters.deviceiocontrol.inputbufferlength; outputlength=irpstack->parameters.deviceiocontrol.outputbufferlength; switch (irpstack->parameters.deviceiocontrol.iocontrolcode) { case ioctl_passbuf: { rtlcopymemory(pirp->userbuffer, outbuf, 20*16); memset(outbuf,0,128*16); count = 0; break; } default: break; } default: dbgprint("call irp_mj_unknown/n"); break; } pirp->iostatus.status = status; pirp->iostatus.information = 0; iocompleterequest (pirp, io_no_increment); return status; } //////////////////////////////// // 1.asm //////////////////////////////// .386 .model small .data _orgret dd 0 .code public _func@0 extrn _cfunc@0:near extrn _hookdestfunction@0:near extrn _orgdestfunction:dword _func@0 proc pushad call _cfunc@0 popad push eax mov eax,[esp+4] mov ds:_orgret,eax pop eax mov [esp],retaddr jmp _orgdestfunction retaddr: pushad call _hookdestfunction@0 popad jmp ds:_orgret _func@0 endp end ////////////////////////////////////////// // app.cpp ////////////////////////////////////////// #include <windows.h> #include <stdio.h> #define file_device_event 0x8000 #define ctl_code( devicetype, function, method, access ) ( / ((devicetype) << 16) | ((access) << 14) | ((function) << 2) | (method) / ) #define file_any_access 0 #define method_buffered 0 #define file_device_unknown 0x00000022 #define ioctl_passbuf / ctl_code(file_device_event, 0x802, method_buffered, file_any_access) int main() { handle hdevice; bool status; ulong dwreturn; char outbuf[129][16]; hdevice = null; m_hcommevent = null; hdevice = createfile( "////.//myevent", generic_read|generic_write, file_share_read | file_share_write, null, open_existing, file_attribute_normal, null); if(hdevice == invalid_handle_value) { printf("createfile wrong/n"); getchar(); return 0; } while(1) { memset(outbuf,0,129*16); status =deviceiocontrol(hdevice, ioctl_passbuf, null, 0, &outbuf, 128*16, &dwreturn,null); if( !status) { printf("io wrong+%d/n", getlasterror()); getchar(); return 0; } int c=0; while( *((char*)(&outbuf)+c*16) ) { //把csrss.exe和自身进程信息跳过,因为会产生有大量的信息。 if ( strcmp((char*)(&outbuf)+c*16,"app.exe") && / strcmp((char*)(&outbuf)+c*16,"csrss.exe") ) printf("%s/n",(char*)(&outbuf)+c*16); c++; } sleep(1); } }
试验结果:
...... ttplayer.exe system ttplayer.exe vrvmon.exe ttplayer.exe system system explorer.exe explorer.exe explorer.exe ......
测试、编译环境windows2000 sp4、windows2000 ddk。没写出线程的隐藏进程代码,不过基本上实现得差不多了,只需要把返回的信息,和ring3级查询得到的信息进行适时对比就能查出异常进程了。
(完)
- 内核级利用通用Hook函数方法检测进程
- 内核级利用通用Hook函数方法检测进程
- 内核级利用通用Hook函数方法检测进程
- 【收藏】内核级利用通用Hook函数方法检测进程
- 内核级利用通用Hook函数方法检测进程
- 内核级利用通用Hook函数方法检测进程
- 内核级利用通用Hook函数方法检测进程
- 内核级利用通用Hook函数方法检测进程
- 内核级利用通用Hook函数方法检测进程
- 内核级利用通用Hook函数方法检测进程
- (转载)利用内核级通用Hook检测系统中的进程
- 利用内核级通用HOOK检测系统中的进程(转载)
- 简析利用调试寄存器实现内核函数的HOOK
- 简析利用调试寄存器实现内核函数的HOOK
- 简析利用调试寄存器实现内核函数的HOOK
- 内核hook NtQuerySystemInformation隐藏进程
- 利用HOOK保护记事本进程
- SSDT Hook实现内核级的进程保护
- Win XP 键盘快捷键大全
- asp.net中自定义日期控件试用
- hibernate 数据源层-O/R Mapping
- Eclipse 下swing 可视化插件 Visual Editor的安装(新手必看)
- Hibernate入门
- 内核级利用通用Hook函数方法检测进程
- JSP树型标签 Tree Tag 用户指南
- 代做计算机毕业设计
- Search Help (搜索帮助)
- 数据表建立相关知识
- 字符串常用技巧
- “知识管理”到底是什么? 转自:廉奇志/KMCenter
- 毕业了是应该考个研还是考个证儿?——写在MBA课程最后的日子里
- 内存管理内幕--动态分配的选择、折衷和实现(一)