还原的C代码在ReactOS的开源中已经给出了,这次只是想看看XP SP3下有什么不同。果然有一个发现,这个函数中有一部分代码在这个函数调用中是没有被执行。所以是hook的好位置。下面的汇编代码已经完全注释,还原成C就没有问题了。这次练习的主要目的是猜测其中局部变量的含义,通过注释此汇编代码,局部变量含义完全给出。凡是局部变量名前面都有一个‘l’作为Local的缩写,以便区分。大家可以通过这个函数动态获取两个SSDT表的入口。
nt!PsConvertToGuiThread: 805c3720 6a38 push 38h 805c3722 6810ac4d80 push offset nt!ObWatchHandles+0x3c4 (804dac10) 805c3727 e8e457f7ff call nt!_SEH_prolog (80538f10)//检查相关句柄信息 805c372c 64a124010000 mov eax,dword ptr fs:[00000124h]//KTHREAD.CurrentThread 805c3732 8bf0 mov esi,eax//CurrentThread 805c3734 33db xor ebx,ebx 805c3736 389e40010000 cmp byte ptr [esi+140h],bl//CurrentThread.PreviousMode==0? 805c373c 750a jne nt!PsConvertToGuiThread+0x28 (805c3748)//为0则跳转 805c373e b80d0000c0 mov eax,0C000000Dh 805c3743 e91f010000 jmp nt!PsConvertToGuiThread+0x147 (805c3867)//不为0则失败 805c3748 391d180b6780 cmp dword ptr [nt!PspW32ProcessCallout (80670b18)],ebx//内核模式,*PspW32ProcessCallout==0? 805c374e 750a jne nt!PsConvertToGuiThread+0x3a (805c375a) 805c3750 b8220000c0 mov eax,0C0000022h//失败 805c3755 e90d010000 jmp nt!PsConvertToGuiThread+0x147 (805c3867) 805c375a 81bee0000000a03f5580 cmp dword ptr [esi+0E0h],offset nt!KeServiceDescriptorTable (80553fa0)//CurrentThread.ServiceTable==KeServiceDescriptorTable? 805c3764 740a je nt!PsConvertToGuiThread+0x50 (805c3770) 805c3766 b81b000040 mov eax,4000001Bh//*PspW32ProcessCallout==NULL,失败 805c376b e9f7000000 jmp nt!PsConvertToGuiThread+0x147 (805c3867) 805c3770 8b4644 mov eax,dword ptr [esi+44h]//线程已经指向KeServiceDescriptorTable,那么KPROCESS CurrentThread.ApcState.Process 805c3773 8945e0 mov dword ptr [ebp-20h],eax//lProcess=CurrentThread.ApcState.Process 805c3776 389e42010000 cmp byte ptr [esi+142h],bl//CurrentThread.LargeStack==0? 805c377c 756a jne nt!PsConvertToGuiThread+0xc8 (805c37e8) 805c377e 33c0 xor eax,eax 805c3780 8a86df000000 mov al,byte ptr [esi+0DFh]//al=CurrentThread.InitialNode 805c3786 50 push eax//CurrentThread.InitialNode 805c3787 6a01 push 1 805c3789 e820b8f4ff call nt!MmCreateKernelStack (8050efae)//创建内核堆栈 805c378e 8bf8 mov edi,eax 805c3790 3bfb cmp edi,ebx//函数是否调用成功 805c3792 752a jne nt!PsConvertToGuiThread+0x9e (805c37be) 805c3794 895dfc mov dword ptr [ebp-4],ebx//tProcessHandle=0 805c3797 64a118000000 mov eax,dword ptr fs:[00000018h]//&kPcr 805c379d 8945dc mov dword ptr [ebp-24h],eax//lkStartPcrAddress=&kPcr 805c37a0 c7403408000000 mov dword ptr [eax+34h],8//lkStartPcrAddress->KdVersionBlock=8 805c37a7 eb07 jmp nt!PsConvertToGuiThread+0x90 (805c37b0) 805c37a9 33c0 xor eax,eax//这里永远不会被当前函数执行,hook的好位置 805c37ab 40 inc eax 805c37ac c3 ret 805c37ad 8b65e8 mov esp,dword ptr [ebp-18h] 805c37b0 834dfcff or dword ptr [ebp-4],0FFFFFFFFh//tProcessHandle=NtCurrentProcess() 805c37b4 b8170000c0 mov eax,0C0000017h//失败 805c37b9 e9a9000000 jmp nt!PsConvertToGuiThread+0x147 (805c3867) 805c37be b101 mov cl,1//内核堆栈分配成功 805c37c0 ff15f4864d80 call dword ptr [nt!_imp_KfRaiseIrql (804d86f4)]//提升IRQL权限 805c37c6 8845e7 mov byte ptr [ebp-19h],al//lOldIrql=al 805c37c9 8d8700d0ffff lea eax,[edi-3000h]//-KERNEL_STACK_SIZE地址 805c37cf 50 push eax 805c37d0 57 push edi 805c37d1 e8bacff3ff call nt!KeSwitchKernelStack (80500790)//交换 805c37d6 8bf8 mov edi,eax 805c37d8 8a4de7 mov cl,byte ptr [ebp-19h]//cl=lOldIrql 805c37db ff151c874d80 call dword ptr [nt!_imp_KfLowerIrql (804d871c)]//降低IRQL权限 805c37e1 53 push ebx//0 805c37e2 57 push edi//刚才MmCreateKernelStack函数返回的参数 805c37e3 e8ceb9f4ff call nt!MmDeleteKernelStack (8050f1b6)//释放资源 805c37e8 a10cbf5580 mov eax,dword ptr [nt!PPerfGlobalGroupMask (8055bf0c)]//线程最大堆栈不为0 805c37ed 3bc3 cmp eax,ebx//那么PPerfGlobalGroupMask[0]==0? 805c37ef 7447 je nt!PsConvertToGuiThread+0x118 (805c3838)//为0则跳转 805c37f1 f6400401 test byte ptr [eax+4],1//PPerfGlobalGroupMask[1]==1? 805c37f5 7441 je nt!PsConvertToGuiThread+0x118 (805c3838)//为1也可以继续运行 805c37f7 8b86ec010000 mov eax,dword ptr [esi+1ECh]//CurrentThread.Cid 805c37fd 8945d0 mov dword ptr [ebp-30h],eax//lCid=CurrentThread.Cid 805c3800 8b86f0010000 mov eax,dword ptr [esi+1F0h]//CurrentThread.Cid.UniqueThread 805c3806 8945d4 mov dword ptr [ebp-2Ch],eax//lTID=CurrentThread.Cid.UniqueThread 805c3809 8b8668010000 mov eax,dword ptr [esi+168h]//CurrentThread.StackBase 805c380f 8945b8 mov dword ptr [ebp-48h],eax//lStackBase=CurrentThread.StackBase 805c3812 8b461c mov eax,dword ptr [esi+1Ch]//CurrentThread.StackLimit 805c3815 8945bc mov dword ptr [ebp-44h],eax//lStackLimit=CurrentThread.StackLimit 805c3818 895dc0 mov dword ptr [ebp-40h],ebx 805c381b 895dc4 mov dword ptr [ebp-3Ch],ebx 805c381e 895dc8 mov dword ptr [ebp-38h],ebx 805c3821 895dcc mov dword ptr [ebp-34h],ebx//这里几个局部变量设置为0 805c3824 c645d8ff mov byte ptr [ebp-28h],0FFh//保留低8位 805c3828 6a24 push 24h 805c382a 8d45b8 lea eax,[ebp-48h] 805c382d 50 push eax//&lStackBase 805c382e 6823050000 push 523h 805c3833 e872ae0900 call nt!PerfInfoLogBytes (8065e6aa)//这里调用这个函数检测相关错误 805c3838 6a01 push 1//PPerfGlobalGroupMask[0]=0或者PPerfGlobalGroupMask[1]==1时 805c383a ff75e0 push dword ptr [ebp-20h]//lProcess 805c383d ff15180b6780 call dword ptr [nt!PspW32ProcessCallout (80670b18)]//初始化lProcess的Win32Process结构 805c3843 3bc3 cmp eax,ebx//判断函数调用是否成功 805c3845 7c20 jl nt!PsConvertToGuiThread+0x147 (805c3867)//跳转失败 805c3847 c786e0000000603f5580 mov dword ptr [esi+0E0h],offset nt!KeServiceDescriptorTableShadow (80553f60)//存在视窗,则用KeServiceDescriptorTableShadow 805c3851 53 push ebx//0 805c3852 56 push esi//CurrentThread 805c3853 ff151c0b6780 call dword ptr [nt!PspW32ThreadCallout (80670b1c)]//初始化线程中的Win32Thread字段 805c3859 3bc3 cmp eax,ebx//判断函数调用是否成 805c385b 7d0a jge nt!PsConvertToGuiThread+0x147 (805c3867)//跳转成功 805c385d c786e0000000a03f5580 mov dword ptr [esi+0E0h],offset nt!KeServiceDescriptorTable (80553fa0) 805c3867 e8df56f7ff call nt!_SEH_epilog (80538f4b) 805c386c c3 ret
时间: 2024-10-12 13:09:10