|
本文接上文,请看上文,链接如下:
http://www.m5home.com/bbs/thread-9305-1-1.html
如果上文没看,此文可以忽略。
下文就是让柳暗花明。
我们上文当中碰到了一个非常麻烦的事情,那就是session=0的驱动,去通知session=2的csrss.exe.
我们尝试的找个session=2的a.exe,往a.exe注一点代码,这个代码就负责通知session=2的csrss
最后发现的是session=2的csrss收到消息后回复给了a.exe,我们驱动里并没有得到通知。
我们所有的问题都是为了得到通知。实际上这里走了很多弯路,实验了很多方法。真的是弄的脑袋爆。
由于快过年的原因,也不卖关子了,很多事情。
直接来说
驱动注入用户线程之跨session通知csrss之真正解决 中的所谓的‘真正’的含义!
这里真正是加了引号,实际上我是重点标记,我说的的确是真正。
当问题没办法解决的时候会怎么办呢?当然是所有的办法也猜测,所有的资料也看。这里我们为了节约时间突出重点。
我们不再说我们走的弯路(实际上弯路很多很多)
当然这其中也免不了看 csrss.exe用了什么模块。自然会关注到CSRSRV.dll
网上搜也会看到这个是csrss.exe的核心。既然我们关注了这个dll.我们也就避免不了看看导出啊,对感兴趣的函数逆逆啊,搜搜啊什么的
我们来看这个dll的导出函数。
如下:
导出, CSRSRV.dll
序列 地址 名字
00000001 75AA544F CsrAddStaticServerThread
00000002 75AA4160 CsrCallServerFromServer 看名字我有兴趣
00000003 75AA3FCE CsrConnectToUser 看名字我有兴趣
00000004 75AA5D26 CsrCreateProcess
00000005 75AA60E0 CsrCreateRemoteThread 看名字我有兴趣
00000006 75AA6010 CsrCreateThread 看名字我有兴趣
00000007 75AA63FE CsrCreateWait
00000008 75AA6362 CsrDebugProcess
00000009 75AA636F CsrDebugProcessStop
0000000A 75AA500B CsrDereferenceProcess
0000000B 75AA55AA CsrDereferenceThread
0000000C 75AA658B CsrDereferenceWait
0000000D 75AA5F58 CsrDestroyProcess
0000000E 75AA619A CsrDestroyThread
0000000F 75AA54C2 CsrExecServerThread
00000010 75AA508D CsrGetProcessLuid
00000011 75AA4EE9 CsrImpersonateClient
00000012 75AA535D CsrLockProcessByClientId
00000013 75AA53DD CsrLockThreadByClientId
00000014 75AA6615 CsrMoveSatisfiedWait
00000015 75AA652D CsrNotifyWait 看名字我有兴趣
00000016 75AA2A17 CsrPopulateDosDevices
00000017 75AA3FC3 CsrQueryApiPort 看名字我有兴趣
00000018 75AA4F9D CsrReferenceThread
00000019 75AA4F30 CsrRevertToSelf
0000001A 75AA305E CsrServerInitialization
0000001B 75AA4D1F CsrSetBackgroundPriority
0000001C 75AA516F CsrSetCallingSpooler
0000001D 75AA4CF8 CsrSetForegroundPriority
0000001E 75AA624F CsrShutdownProcesses
0000001F 75AA3204 CsrUnhandledExceptionFilter
00000020 75AA53BA CsrUnlockProcess
00000021 75AA622C CsrUnlockThread
00000022 75AA4421 CsrValidateMessageBuffer
00000023 75AA449D CsrValidateMessageString
我有兴趣的函数我都在reatos里面搜了。
当搜到CsrCreateRemoteThread函数的时候,一切都傻眼了。为什么呢?我们来看CsrCreateRemoteThread的代码。
路径如下:
subsystems\csr\csrsrv\thread.c
代码以及注释如下:
/*++
* @name CsrCreateRemoteThread
* @implemented NT4
*
* The CsrCreateRemoteThread routine creates a CSR Thread object for
* an NT Thread which is not part of the current NT Process.
*
* @param hThread
* Handle to an existing NT Thread to which to associate this
* CSR Thread.
*
* @param ClientId
* Pointer to the Client ID structure of the NT Thread to associate
* with this CSR Thread.
*
* @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
* othwerwise.
*
* @remarks None.
*
*--*/
NTSTATUS
NTAPI
CsrCreateRemoteThread(IN HANDLE hThread,
IN PCLIENT_ID ClientId)
{
NTSTATUS Status;
HANDLE ThreadHandle;
PCSR_THREAD CsrThread;
PCSR_PROCESS CsrProcess;
KERNEL_USER_TIMES KernelTimes;
DPRINT("CSRSRV: %s called\n", __FUNCTION__);
/* Get the Thread Create Time */
Status = NtQueryInformationThread(hThread,
ThreadTimes,
(PVOID)&KernelTimes,
sizeof(KernelTimes),
NULL);
/* Lock the Owner Process */
Status = CsrLockProcessByClientId(&ClientId->UniqueProcess,
&CsrProcess);
/* Make sure the thread didn't terminate */
if (KernelTimes.ExitTime.QuadPart)
{
/* Unlock the process and return */
CsrUnlockProcess(CsrProcess);
return STATUS_THREAD_IS_TERMINATING;
}
/* Allocate a CSR Thread Structure */
if (!(CsrThread = CsrAllocateThread(CsrProcess)))
{
DPRINT1("CSRSRV:%s: out of memory!\n", __FUNCTION__);
CsrUnlockProcess(CsrProcess);
return STATUS_NO_MEMORY;
}
/* Duplicate the Thread Handle */
Status = NtDuplicateObject(NtCurrentProcess(),
hThread,
NtCurrentProcess(),
&ThreadHandle,
0,
0,
DUPLICATE_SAME_ACCESS);
/* Allow failure */
if (!NT_SUCCESS(Status)) ThreadHandle = hThread;
/* Save the data we have */
CsrThread->CreateTime = KernelTimes.CreateTime;
CsrThread->ClientId = *ClientId;
CsrThread->ThreadHandle = ThreadHandle;
CsrThread->Flags = 0;
/* Insert the Thread into the Process */
CsrInsertThread(CsrProcess, CsrThread);
/* Release the lock and return */
CsrUnlockProcess(CsrProcess);
return STATUS_SUCCESS;
}
CsrCreateRemoteThread(IN HANDLE hThread,IN PCLIENT_ID ClientId)
从注释和内容看,这明摆着不就是:把我们要注的目标进程的hThread和ClientId传给这个函数,这个函数
自动进行关联起来的内置操作吗?
又是一个挖槽。我们干嘛总是驱动里给他发通知,这不是自己自寻死路吗,我们为什么不
为什么不
为什么不
为什么不
太重要了这点信息,下面说的这点信息将是重点中的重点。通篇废话就是为了下面的这几句。
*********************************************************************************************
我们再来回想一下,我们通篇都在做什么?都在做一件事情,那就是 驱动(session=0) 通知 csrss(session=2)
我们从来就没想过往csrss(session=2)里面注,现在人家csrss(session=2)有个现成的函数自己实现这些。
我们现在就往csrss(session=2)里面注,让csrss自己通知自己。而我们驱动不等port的返回,因为所有的关于
port等的信息都tmd与我们没关系了。我们只等着 注入csrss(session=2)里面的 的一点代码 把CsrCreateRemoteThread
的返回值通过结束线程的接口给传回来。
来点片段代码说清楚上面的看似模糊的话。
片段1:r3里的
注入csrss(session=2)里面的 的一点代码,实际上重点就这两行,当然是r3的代码
//csrss自己去处理通知吧,我们什么也不管,我们只管驱动把这两参数给传好就行了。就让csrss自己通知自己
CsrCreateRemoteThread(ThreadHandle,UniqueProcess);
//如果执行到这里的话肯定上面的代码就已经完成了,下面的这行代码是为了让驱动知道(驱动里可以恢复真正的线程运行了)
NtTerminateThread(GetCurrentThread(),0);
片段2:r0里的
MyZwCreateThread()
{
//栈
//上先文
//ZwCreateThread目标线程挂起
//ZwCreateThread(&CsrssThreadHandle, THREAD_ALL_ACCESS...) 目标线程所在进程所在session的 csrss 不挂起(内容就是片段1里的)
//ZwWaitForSingleObject(CsrssThreadHandle...)
//恢复目标进程
}
已经非常清晰了,重点中的重点啊,真的是放血了。
这样做的好处太多了。简单明了,不用那个通知函数又复杂又麻烦,事情又多,弯路又多,网上又很多忽悠人的看似可以的文章。让大家更加迷茫。
简单几行替代上百行,又稳定又安全又有依据。
*********************************************************************************************
所以标题可以这么称呼:
驱动注入用户线程之跨session通知csrss之真正解决之CsrCreateRemoteThread大法之全球首创
哈哈,够霸气吧~~
因为上给加精了,实在不好意思拖到过年了。干脆赶个夜,也不卖关子,直接发出来。
同时提前祝大家2018年,新年快乐!
感谢busy,感谢m5home 感谢ta,感谢所有帮助过我的朋友。
|
评分
-
查看全部评分
|