writeby weolar:http://hi.baidu.com/weolar/blog/item/79e64634ecca8942241f14a2.html/cmtid/f9e7d51b9cfcdad8ac6e756b#f9e7d51b9cfcdad8ac6e756b
刚才第八个门写了个在内核创建进程,以为结束了,不过细细研究,
发现有个小问题,也就是zhuwg说的
和csrss通信问题。这个问题直接导致他那个创建法有错误,
最后会弹出一个对话框来提示进程初始化失败。
当时没怎么管,休息了几天后细细调试了番整个windows进程启动的最后与csrss通信部分,
发现还是有点收获的,
过程也走了点弯路,所以发了出来以防自己忘记。
先不说最后结果,来说说怎么调试出来,我想这个比结果更有意义吧
。首先用spywin确认发现那个对话框是csrss弹出。
于是启动内核调试器,切换到csrss的进程中观察堆栈,果然发现了点有意思的东西,
原来是csrss的CsrApiRequestThread
弹出。好在这个函数是有代码的,在nt4或者reactOS里能直接看到。
读后发现原来这个线程就是csrss处理外部各种请求的
线程,并通过LPC通信。里面通过NtReplyWaitReceivePort不断获取外界消息。
这里的对话框也是这个线程执行如
LoadedServerDll->HardErrorRoutine(……)的代码弹出的。
这里牵扯到LPC的流程,这里可以简单结合csrss说下:
每当有消息发来,NtReplyWaitReceivePort的ReceiveMsg参数的ReceiveMsg.h.u2.s2.Type字段保存了消息的类型,
也就是指示CsrApiRequestThread下一步要进行什么。如果是LPC_REQUEST,ReceiveMsg.ApiNumber则将起到一个回调序列号的
作用:
ApiNumber = ReceiveMsg.ApiNumber;
ServerDllIndex = CSR_APINUMBER_TO_SERVERDLLINDEX( ApiNumber );
LoadedServerDll = CsrLoadedServerDll[ ServerDllIndex ]
(*(LoadedServerDll->ApiDispatchTable[ ApiTableIndex ]))(
&ReceiveMsg,
&ReplyStatus
);
下面来看进程启动时整个csrss的通信流程:父进程创建的最后阶段会通过
CsrClientCallServer将自己的PID,TID,子进程的
句柄,PID发送给CsrApiRequestThread。这时其会通过
CsrLocateThreadByClientId查询父进程的相关信息。然后调用:
CSRSRV!CsrCreateProcess来将子进程信息存储到csrss的hash表中。
上面说的CsrLocateThreadByClientId也是在这个hash表中查询,
下面是调用栈:
005afe78 75ab4eea 0000034c 00000148 005aff1c CSRSRV!CsrCreateProcess (FPO: [6,12,0])
005afed0 75aa4a47 0000034c 005affd8 00000005 basesrv!BaseSrvCreateProcess+0x13f (FPO: [2,11,4])
005afff4 00000000 00000090 00000000 00000000 CSRSRV!CsrApiRequestThread+0x431 (FPO: [Non-Fpo])
下面是PCSR_THREAD
CsrLocateThreadByClientId(
OUT PCSR_PROCESS *Process OPTIONAL,
IN PCLIENT_ID ClientId
)
{
ULONG Index;
PLIST_ENTRY ListHead, ListNext;
PCSR_THREAD Thread;
Index = THREAD_ID_TO_HASH(ClientId->UniqueThread);
if (ARGUMENT_PRESENT(Process)) {
*Process = NULL;
}
ListHead = &CsrThreadHashTable[Index];
ListNext = ListHead->Flink;
while (ListNext != ListHead) {
Thread = CONTAINING_RECORD( ListNext, CSR_THREAD, HashLinks );
if ( Thread->ClientId.UniqueThread == ClientId->UniqueThread &&
Thread->ClientId.UniqueProcess == ClientId->UniqueProcess ) {
if (ARGUMENT_PRESENT(Process)) {
*Process = Thread->Process;
}
return Thread;
}
ListNext = ListNext->Flink;
}
return NULL;
}
KeReleaseSemaphore( ConnectionPort->MsgQueue.Semaphore,
1,
1,
FALSE );
NTSTATUS
CsrApiHandleConnectionRequest(
IN PCSR_API_MSG Message
)
{
NTSTATUS Status;
REMOTE_PORT_VIEW ClientView;
BOOLEAN AcceptConnection;
HANDLE PortHandle;
PCSR_PROCESS Process;
PCSR_THREAD Thread;
PCSR_API_CONNECTINFO ConnectionInformation;
ConnectionInformation = &Message->ConnectionRequest;
AcceptConnection = FALSE;
AcquireProcessStructureLock();
Thread = CsrLocateThreadByClientId( NULL, &Message->h.ClientId );
if (Thread != NULL && (Process = Thread->Process) != NULL) {
Status = NtDuplicateObject( NtCurrentProcess(),
CsrObjectDirectory,
Process->ProcessHandle,
&ConnectionInformation->ObjectDirectory,
0,
0,
DUPLICATE_SAME_ACCESS |
DUPLICATE_SAME_ATTRIBUTES
);
if (NT_SUCCESS( Status )) {
Status = CsrSrvAttachSharedSection( Process,
ConnectionInformation
);
if (NT_SUCCESS( Status )) {
#if DBG
ConnectionInformation->DebugFlags = CsrDebug;
#endif
AcceptConnection = TRUE;
}
}
}
ReleaseProcessStructureLock();
ClientView.Length = sizeof( ClientView );
ClientView.ViewSize = 0;
ClientView.ViewBase = 0;
Status = NtAcceptConnectPort( &PortHandle,
AcceptConnection ? (PVOID)Process->SequenceNumber : 0,
&Message->h,
AcceptConnection,
NULL,
&ClientView
);
if (NT_SUCCESS( Status ) && AcceptConnection) {
IF_CSR_DEBUG( LPC ) {
DbgPrint( "CSRSS: ClientId: %lx.%lx has ClientView: Base=%lx, Size=%lx\n",
Message->h.ClientId.UniqueProcess,
Message->h.ClientId.UniqueThread,
ClientView.ViewBase,
ClientView.ViewSize
);
}
Process->ClientPort = PortHandle;
Process->ClientViewBase = (PCH)ClientView.ViewBase;
Process->ClientViewBounds = (PCH)ClientView.ViewBase +
ClientView.ViewSize;
Status = NtCompleteConnectPort( PortHandle );
if (!NT_SUCCESS( Status )) {
IF_DEBUG {
DbgPrint( "CSRSS: NtCompleteConnectPort - failed. Status == %X\n",
Status
);
}
// FIX, FIX - need to destroy Session
}
}
else {
if (!NT_SUCCESS( Status )) {
IF_DEBUG {
DbgPrint( "CSRSS: NtAcceptConnectPort - failed. Status == %X\n",
Status
);
}
}
else {
IF_DEBUG {
DbgPrint( "CSRSS: Rejecting Connection Request from ClientId: %lx.%lx\n",
Message->h.ClientId.UniqueProcess,
Message->h.ClientId.UniqueThread
);
}
}
}
return Status;
}
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)