首页
社区
课程
招聘
[原创]详解进程创建中与csrss的通信流程
发表于: 2010-5-15 18:11 21177

[原创]详解进程创建中与csrss的通信流程

2010-5-15 18:11
21177

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期)

收藏
免费 7
支持
分享
最新回复 (15)
雪    币: 152
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
表示围观卖油条的
2010-5-15 18:44
0
雪    币: 320
活跃值: (283)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
3
顶楼主! win32子系统很值得挖掘
2010-5-15 18:47
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
纯支持,不搞编程很多年
2010-5-15 18:48
0
雪    币: 142
活跃值: (22)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
5
来看大N的教程先
2010-5-15 18:51
0
雪    币: 306
活跃值: (10)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
6
项盟主。期待山windbg
2010-5-15 18:53
0
雪    币: 695
活跃值: (25)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
7
盟主大侠千秋万载,一统江湖!!!
2010-5-15 18:53
0
雪    币: 168
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
盟主啥意思?
2010-5-15 19:33
0
雪    币: 248
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
学学收藏了.......
2010-5-15 19:51
0
雪    币: 433
活跃值: (1870)
能力值: ( LV17,RANK:1820 )
在线值:
发帖
回帖
粉丝
10
去他博客看下就知道了
2010-5-16 11:27
0
雪    币: 1335
活跃值: (5190)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
11
谢谢盟主....
2010-5-26 18:51
0
雪    币: 1505
能力值: (RANK:210 )
在线值:
发帖
回帖
粉丝
12
楼主有没有尝试过把这部分工作不使用csrss.exe
而是自己在父进程实现?
其实从实际应用来说,还是这个或者子自实现csrssclientcallserver好用.
而后面引用了全局变量,搜索的话又不敢保证支持所有操作系统.
2010-5-27 00:04
0
雪    币: 1505
能力值: (RANK:210 )
在线值:
发帖
回帖
粉丝
13
看了下几个包括楼主的和自己做的CreateProcess,都是要调用ClientCallServer的.
可能有点吹毛求疵了,呵呵.
2010-5-27 00:07
0
雪    币: 364
活跃值: (152)
能力值: ( LV12,RANK:450 )
在线值:
发帖
回帖
粉丝
14
不使用csr不太可能吧,kernel32的初始化必须要和csr通信,各种gui的功能也要和csr通信。
要通信成功,父进程就必须在csr里有记载。欢迎大家提出更好的方案。
2010-5-27 09:15
0
雪    币: 81
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
楼主头像很**,纯支持!
2010-5-27 10:13
0
雪    币: 239
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
哈哈,谢谢楼主 解答我的问题~~我定当好好研究~~~
2010-7-22 01:26
0
游客
登录 | 注册 方可回帖
返回
//