windbg学习笔记 FOR 内核调试(四) -- PspTerminateThreadByPointer

windbg学习笔记 FOR 内核调试(四) -- PspTerminateThreadByPointer

      近日事情颇多 喝茶拉 吃好吃的还有看电影啊~磨去不少时间,甚欢.难得放假回家 一直被拉出去也没看什么东西 前段时间刚跟鼠仙讨论了下 我跑去看了下进程保护的一些东东,但是肤浅的很 就研究了下WRK的一些代码 发现关闭进程都跟这个PspTerminateThreadByPointer函数有关,NtProcess的代码很简单,就是得到进程的EPROCESS 然后遍历它的线程链表 接着就一个个用 PspTerminateThreadByPointer 函数挂掉就OK  也就是说想要保护进程 挂钩个 PspTerminateThreadByPointer 效果还是很理想的    反正拿这个去实现R3下进程保护应该绰绰有余了
为了练习下windbg的使用 准备随便跟下我们的 PspTerminateThreadByPointer 函数 冰刃刚下速度太慢了 我就用任务管理器试验的 呵呵

首先开虚拟机,然后一阵啰嗦的操作后进入正题

先给我们的函数下个断
kd> bp nt!PspTerminateThreadByPointer

我们bl看看
kd> bl
 0 e 805c9b8e     0001 (0001) nt!PspTerminateThreadByPointer

OK 成功了 然后打开任务管理器 在随便打开个程序  INSTDRV.exe  (平时加载驱动用的,呵呵)

然后拿任务管理器做掉这个进程 HOHO~~

Breakpoint 0 hit
nt!PspTerminateThreadByPointer:
805c9b8e 8bff            mov     edi,edi

断下来了  汇编显示的是这个函数的第一条语句 不过这个命令无任何意义

拿k指令看看函数堆栈

kd> k
ChildEBP RetAddr 
f7932d28 805c9d8b nt!PspTerminateThreadByPointer
f7932d54 8053e648 nt!NtTerminateProcess+0xd5
f7932d54 7c92e4f4 nt!KiFastCallEntry+0xf8
0007f73c 7c92de5c ntdll!KiFastSystemCallRet
0007f740 7c801e3a ntdll!ZwTerminateProcess+0xc

喃~函数堆栈是个好东西  呵呵  那么我们结束进程的过程就清楚了 由于后面的函数堆栈没法显示 不知道为什么 反正差不多的调用流程就是这样
ZwTerminateProcess- NtTerminateProcess - PspTerminateThreadByPointer 中间那2个函数干嘛用的我就不太清楚了   反了下 ZwTerminateProcess
kd> uf nt!zwterminateprocess
nt!ZwTerminateProcess:
805001bc b801010000      mov     eax,101h
805001c1 8d542404        lea     edx,[esp+4]
805001c5 9c              pushfd
805001c6 6a08            push    8
805001c8 e8c4e20300      call    nt!KiSystemService (8053e491)
805001cd c20800          ret     8

nt!KiSystemService这个函数好像是跟SSDT有关 估计就是跑去找NtProcess的地址的吧 那么中间那2个函数可以自己意淫一下应该就是 进行用户态和内核态之间的切换了~
不知道是不是这样的  希望哪位大牛可以解答下小弟的推测正确与否~ 在此谢过~!

然后单步调试开始了 嘿嘿 为了方便看 我重新断了次(之前拿r指令开了显示寄存器信息开关了 呵呵)
Breakpoint 0 hit
eax=81308da8 ebx=81299020 ecx=00000000 edx=00000000 esi=81308da8 edi=8130dda8
eip=805c9b8e esp=f7932d2c ebp=f7932d54 iopl=0         nv up ei ng nz na pe cy
cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000             efl=00000287
nt!PspTerminateThreadByPointer:
805c9b8e 8bff            mov     edi,edi
kd> t
eax=81308da8 ebx=81299020 ecx=00000000 edx=00000000 esi=81308da8 edi=8130dda8
eip=805c9b90 esp=f7932d2c ebp=f7932d54 iopl=0         nv up ei ng nz na pe cy
cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000             efl=00000287
nt!PspTerminateThreadByPointer+0x2:
805c9b90 55              push    ebp
kd> t
eax=81308da8 ebx=81299020 ecx=00000000 edx=00000000 esi=81308da8 edi=8130dda8
eip=805c9b91 esp=f7932d28 ebp=f7932d54 iopl=0         nv up ei ng nz na pe cy
cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000             efl=00000287
nt!PspTerminateThreadByPointer+0x3:
805c9b91 8bec            mov     ebp,esp
kd> t
eax=81308da8 ebx=81299020 ecx=00000000 edx=00000000 esi=81308da8 edi=8130dda8
eip=805c9b93 esp=f7932d28 ebp=f7932d28 iopl=0         nv up ei ng nz na pe cy
cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000             efl=00000287
nt!PspTerminateThreadByPointer+0x5:
805c9b93 83ec0c          sub     esp,0Ch ; 貌似是切换栈了~
kd> t
eax=81308da8 ebx=81299020 ecx=00000000 edx=00000000 esi=81308da8 edi=8130dda8
eip=805c9b96 esp=f7932d1c ebp=f7932d28 iopl=0         nv up ei ng nz ac po nc
cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000             efl=00000292
nt!PspTerminateThreadByPointer+0x8:
805c9b96 834df8ff        or      dword ptr [ebp-8],0FFFFFFFFh ss:0010:f7932d20=00000008
kd> t
eax=81308da8 ebx=81299020 ecx=00000000 edx=00000000 esi=81308da8 edi=8130dda8
eip=805c9b9a esp=f7932d1c ebp=f7932d28 iopl=0         nv up ei ng nz na pe nc
cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000             efl=00000286
nt!PspTerminateThreadByPointer+0xc:
805c9b9a 56              push    esi
kd> t
eax=81308da8 ebx=81299020 ecx=00000000 edx=00000000 esi=81308da8 edi=8130dda8
eip=805c9b9b esp=f7932d18 ebp=f7932d28 iopl=0         nv up ei ng nz na pe nc
cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000             efl=00000286
nt!PspTerminateThreadByPointer+0xd:
805c9b9b 57              push    edi ; 注意这里 原来的esi在ebp+8处
kd> t
eax=81308da8 ebx=81299020 ecx=00000000 edx=00000000 esi=81308da8 edi=8130dda8
eip=805c9b9c esp=f7932d14 ebp=f7932d28 iopl=0         nv up ei ng nz na pe nc
cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000             efl=00000286
nt!PspTerminateThreadByPointer+0xe:
805c9b9c 8b7d08          mov     edi,dword ptr [ebp+8] ss:0010:f7932d30=81308da8
;喃~他把原来esi的值传给edi了
kd> t
eax=81308da8 ebx=81299020 ecx=00000000 edx=00000000 esi=81308da8 edi=81308da8
eip=805c9b9f esp=f7932d14 ebp=f7932d28 iopl=0         nv up ei ng nz na pe nc
cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000             efl=00000286
nt!PspTerminateThreadByPointer+0x11:
805c9b9f 8db748020000    lea     esi,[edi+248h]
;wrk上有条语句如下
 if (Thread->CrossThreadFlags
    & PS_CROSS_THREAD_FLAGS_BREAK_ON_TERMINATION)
然后根据这个 lea     esi,[edi+248h] 命令看来 貌似edi指向的是个ETHREAD结构 应为
ETHREAD偏移248处就是这个CrossThreadFlags成员变量
kd> dt _ethread
ntdll!_ETHREAD
   +0x000 Tcb              : _KTHREAD
   [...]
   +0x248 CrossThreadFlags : Uint4B
   [...]
那么就是说edi存放的是ethread的地址,上个命令
mov     edi,dword ptr [ebp+8]就是把原esi的值传给edi的
可见第一个参数是保存在esi中的   那我们来看看这个ethread的结构
现在edi中存放的是ethread的地址
kd> r esi
esi=81308da8

然后
kd> dt _ethread 81308da8
ntdll!_ETHREAD
   +0x000 Tcb              : _KTHREAD
   [...]
   +0x1d0 ExitStatus       : 0
   [...]
   +0x220 ThreadsProcess   : 0x81299020 _EPROCESS
   [...]
找到 ThreadsProcess  它的值是 0x81299020 这个就是线程对应的进程结构地址
kd> dt _eprocess 0x81299020
ntdll!_EPROCESS
   +0x000 Pcb              : _KPROCESS
   [...]
   +0x174 ImageFileName    : [16]  "INSTDRV.EXE"
   [...]
看~"INSTDRV.EXE"是我们要结束的那个进程吧~呵呵
PspTerminateThreadByPointer的函数原型是这样的
NTSTATUS
PspTerminateThreadByPointer(
    IN PETHREAD Thread,
    IN NTSTATUS ExitStatus,
    IN BOOLEAN DirectTerminate
    )
第一个参数就是要做掉的线程结构 要结束进程得把这个进程下所有线程挂掉 刚我们断下PspTerminateThreadByPointer 拿第一个指向的结构一路跟踪过来就找到了这个"INSTDRV.EXE" eprocess
神奇吧~HOHO~

到这里我一度很是奇怪,咋个参数传递不都是通过栈传递的吗 
我发现PspTerminateThreadByPointer的函数调用好像是第一个参数在esi里面
第二个参数不知道是不是在edi里面 那么~~第三个参数在哪....

我好像之前有略过一篇文章说到这个windows堆栈传递忘了是那篇文章了...

一会要去T球了 暂时打住...
汇编好多指令不懂...先去修炼内功先...再好好研究这个函数吧 呵呵
                                                                                                                                                 __ay.字




你可能感兴趣的:(windbg学习笔记 FOR 内核调试(四) -- PspTerminateThreadByPointer)