writeby weolar:2baK9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8X3S2A6i4K6u0W2j5X3q4A6k6s2g2Q4x3X3g2U0L8$3#2Q4x3V1k6%4k6h3!0D9j5i4u0Q4x3V1k6T1L8r3!0Y4i4K6u0r3K9i4c8W2L8g2)9J5c8U0M7&6k6e0j5@1y4U0x3@1k6h3y4U0j5e0R3&6y4o6t1J5y4o6q4X3x3e0c8S2x3W2)9J5k6h3S2@1L8h3I4Q4x3V1k6U0L8i4c8A6k6q4)9J5c8X3j5&6k6e0N6V1y4e0q4T1z5h3y4X3j5$3c8S2k6o6S2S2j5K6k6W2y4K6f1$3j5W2)9J5x3$3j5&6k6e0N6V1y4e0q4T1z5h3y4X3j5$3c8S2k6o6S2S2j5K6k6W2y4K6f1$3j5R3`.`.
刚才第八个门写了个在内核创建进程,以为结束了,不过细细研究,
发现有个小问题,也就是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;
}
[培训]科锐逆向工程师培训第53期2025年7月8日开班!