2012年7月5日星期四

shadow_ssdt_hook.asm


;filename:shadow_ssdt_hook.asm
;made by correy
;QQ:112426112
;Email:leguanyuan at 126 dot com
;HomePage:http://correy.webs.com
;不足之处敬请指点
;在实机上有时候会蓝屏,可能是AttachProcess引起的吧!
;但这是极个别的情况下,打开anti-rootlit-tools时。
;更有趣的是有些工具,却发现不了这个hook.

;顺便说一下编译方式:
;rc me.rc >error.txt ;这个可有可无。
;ml /nologo /c /coff /Zp4 shadow_ssdt_hook.asm >>error.txt
;link /nologo /driver /base:0x10000 /align:16 /out:sys.sys /subsystem:native /section:.text,rw /MERGE:.rdata=.text shadow_ssdt_hook.obj me.res>>error.txt
;如果想得到调试信息,在ml命令行中加入,/Cp /Zi,在link中加入 /DEBUG /DEBUGTYPE:CV.不过本人,不喜欢这两个参数。很少使用。
;出错信息在error.txt中查看。

.386
.model flat, stdcall
option casemap:none

include ntstatus.inc
include ntddk.inc
include ntoskrnl.inc
includelib ntoskrnl.lib
include Strings.mac

.code
y dd 0
prs db 18 dup (0) ;KAPC_STATE STRUCT

GetServiceDescriptorTableShadowAddress proc uses esi edi ebx
;本函数摘自kmdkit。本人加一些注释,及自己的理解。
local dwThreadId:DWORD

  xor ebx, ebx        ; = NULL. Assume ServiceDescriptorTableShadow will be not found

  mov eax, KeServiceDescriptorTable
  mov esi, [eax]

  ; Find KTHREAD.ServiceTable field
  ; For non-GUI threads this field == KeServiceDescriptorTable
  ; and it points to ServiceDescriptorTable
  ; For GUI threads
  ; ServiceDescriptorTableShadow

  invoke KeGetCurrentThread  ;得到KTHREAD的结构。
  mov edi, 1;200h-4            ;为什么是这个数呢?换成1,inc edi呢?
  .while edi
    .break .if dword ptr [eax][edi] == esi ;经查资料0x0e0 ServiceTable : Ptr32 Void。
    inc edi;dec edi
  .endw

  .if edi != 0
    ; edi = offset to ServiceTable field in KTHREAD structure
    mov dwThreadId, 080h      ;为什么是这个数呢?
    .while dwThreadId < 400h  ;为什么是这个数呢?
      push eax          ; reserve DWORD on stack
      invoke PsLookupThreadByThreadId, dwThreadId, esp
      pop ecx            ; -> ETHREAD/KTHREAD
      .if eax == STATUS_SUCCESS
        push dword ptr [ecx][edi] ;这就是那个表,ssdt或者shadow.
        fastcall ObfDereferenceObject, ecx
        pop eax ;这儿就应该是返回值。
        .if eax != esi ;如果这是一个GUI线程。就返回结束吧!
        
          mov edx, MmSystemRangeStart ;这三行,得到的数是80000000,特殊的可能是c0000000h.
          mov edx, [edx]
          mov edx, [edx]
          
          .if eax > edx    ; some stupid error checking  真是!这里的判断太多余。
            mov ebx, eax
            invoke DbgPrint, $CTA0("FindShadowTable: Found in thread with ID: %X\n"), dwThreadId
            .break
          .endif
          
        .endif
      .endif
      add dwThreadId, 4 ;为什么加4呢?
    .endw
  .endif

  mov eax, ebx
  ret

GetServiceDescriptorTableShadowAddress endp

szeax db "eax == %x",0
szNtUserFindWindowEx db "NtUserFindWindowEx is called",0

myhookfun proc x1,x2,x3,x4,x5
;这个函数是:NtUserFindWindowEx。
;要获取与附加一些功能,就在这里设置吧!
;我就在这里打印一个信息吧!
  
  invoke DbgPrint,addr szNtUserFindWindowEx
  
  push x5
  push x4
  push x3
  push x2
  push x1
  call y
  
  push eax  ;此三行是检测,可以不要。
  invoke DbgPrint,addr szeax,eax
  pop eax
  
ret
myhookfun endp

correy db "ok",0
szcsrss db "csrss.exe",0
DriverEntry proc pDriverObject:PDRIVER_OBJECT, pusRegistryPath:PUNICODE_STRING
local tem:dword
local e:dword
local z:dword 
local x:dword 
  
  push eax;另一种办法是mdl,甚么的。
  ;cli
  mov eax, cr0;
  mov tem, eax;
  and eax, 0FFFEFFFFh;
  mov cr0, eax;
  pop eax;
  
  ;int 3 
  
  invoke PsGetCurrentProcess
  
  mov edx,[eax+88h] ;跳过自身,也就是第一个。可以确定这个不是?是system?还有一个是smss.exe
  
  .while edx!=0
    
    mov e,edx
    
    mov esi,edx
    add esi,0ech;174h
    mov z,edx
    invoke _strnicmp,esi, addr szcsrss,9 ;这个函数的调用方式像c/c++.
    
    .if eax == 0
      mov edx,z
      sub edx,88h
      invoke KeAttachProcess,edx
      ;invoke KeStackAttachProcess,edx,addr prs ;微软推荐用这个函数。
      invoke DbgPrint,addr correy ;检测信息,多余的。
      ;int 3
      mov edx,z ;这个变量是多余的,主要用来是查看值的。
      .break ;这一句其实是个调转指令。jmp.
    .endif
    
    mov edx,dword ptr [e]
    mov edx,[edx]
  .endw
  ;以上的代码是确保下面的代码正确运行。有好多多余的变量,与垃圾的指令,下面也是。
  
  invoke GetServiceDescriptorTableShadowAddress
  mov eax,[eax+16]
  add eax,17ah*4 ;无法用MmGetSystemRoutineAddress函数获得。 hook的是NtUserFindWindowEx。
                 ;找不到相关的资料,只能调试反汇编了,但还得有办法。
  
  ;int 3
  mov esi,dword ptr [eax] ;此句运行失败。
  
  mov x,esi ;这两行多余不?只为下面一行运行正确。
  mov ecx,x
  mov y,ecx;esi ;存储要hook的函数的原始的地址。他妈的,这一句也会运行失败。
  
  mov dword ptr [eax],offset myhookfun

  push eax; 不用说了吧!
  mov eax,tem
  mov cr0, eax;
  pop eax;
  ;sti

  mov eax, 0
  ret

DriverEntry endp

end DriverEntry
;made at 2011.06.25
;没有卸载函数,你找工具卸载吧!

没有评论:

发表评论