亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? 漫談兼容內核之十八:windows的lpc機制.txt

?? 漫談系統內核內幕 收集得很辛苦 呵呵 大家快下在吧
?? TXT
?? 第 1 頁 / 共 4 頁
字號:
       CRequest = (PEPORT_CONNECT_REQUEST_MESSAGE)&Request->Message;
       memcpy(&Header, &Request->Message, sizeof(LPC_MESSAGE));
       Header.DataSize = CRequest->ConnectDataLength;
       Header.MessageSize = Header.DataSize + sizeof(LPC_MESSAGE);
       Status = MmCopyToCaller(LpcMessage, &Header, sizeof(LPC_MESSAGE));
       if (NT_SUCCESS(Status))
       {
         Status = MmCopyToCaller((PVOID)(LpcMessage + 1),
                         CRequest->ConnectData, CRequest->ConnectDataLength);
       }
   }
   else
   {
       Status = MmCopyToCaller(LpcMessage, &Request->Message,
                                   Request->Message.MessageSize);
   }
   . . . . . .
   if (Request->Message.MessageType == LPC_CONNECTION_REQUEST)
   {
       KeAcquireSpinLock(&Port->Lock, &oldIrql);
       EiEnqueueConnectMessagePort(Port, Request);
       KeReleaseSpinLock(&Port->Lock, oldIrql);
   }
   else
   {
       ExFreePool(Request);
   }
  
   /* Dereference the port */
   ObDereferenceObject(Port);
   return(STATUS_SUCCESS);
}[/code]

    在Port機制的實現中,NtReplyWaitReceivePortEx()是個經常用到的函數。剛才我們看到的是從NtListenPort()逐層調用下來的,所以沒有應答報文需要發送,直接就進入等待接收報文的階段了,但在多數情況下是有應答報文要發送的,服務線程運行的典型情景就是“接收-處理-應答-再接收”,所以把應答和再接收合并在一起。因此,我們也應看一下在有應答報文要發送時的操作,就是代碼中if (LpcReply != NULL && !Disconnected)語句里面的操作。
    當然,如果端口已經處于斷開狀態、即Disconnected為TRUE,那就不發送應答報文了。從代碼中可以看出,應答報文的發送是通過EiReplyOrRequestPort()完成的。完成以后還要向對方端口的“信號量”執行一次V操作,即增量為1的KeReleaseSemaphore()操作,如果對方線程正在睡眠等待就把它喚醒。后面這一步屬于線程間同步,讀者想必已經熟悉了,這里看一下EiReplyOrRequestPort()的代碼:

[code][NtReplyWaitReceivePort() > NtReplyWaitReceivePortEx()> EiReplyOrRequestPort()]

NTSTATUS STDCALL
EiReplyOrRequestPort (IN PEPORT  Port,
                     IN PLPC_MESSAGE  LpcReply,
                     IN ULONG  MessageType,
                     IN PEPORT  Sender)
{
   . . . . . .

   MessageReply = ExAllocatePoolWithTag(NonPagedPool, sizeof(QUEUEDMESSAGE),
                                                      TAG_LPC_MESSAGE);
   MessageReply->Sender = Sender;
  
   if (LpcReply != NULL)
   {
      memcpy(&MessageReply->Message, LpcReply, LpcReply->MessageSize);
   }
   MessageReply->Message.ClientId.UniqueProcess = PsGetCurrentProcessId();
   MessageReply->Message.ClientId.UniqueThread = PsGetCurrentThreadId();
   MessageReply->Message.MessageType = MessageType;
   MessageReply->Message.MessageId = InterlockedIncrementUL(&LpcpNextMessageId);
  
   KeAcquireSpinLock(&Port->Lock, &oldIrql);
   EiEnqueueMessagePort(Port, MessageReply);
   KeReleaseSpinLock(&Port->Lock, oldIrql);
  
   return(STATUS_SUCCESS);
}[/code]
    參數LpcReply是從上面傳下來的指針,指向一個LPC_MESSAGE數據結構,這就是待發送的報文。下面是LPC_MESSAGE數據結構的格式定義:

[code]typedef struct _LPC_MESSAGE {
USHORT  DataSize;
USHORT  MessageSize;
USHORT  MessageType;
USHORT  VirtualRangesOffset;
CLIENT_ID  ClientId;
ULONG  MessageId;
ULONG  SectionSize;
UCHAR  Data[ANYSIZE_ARRAY];
} LPC_MESSAGE, *PLPC_MESSAGE;[/code]

    實際上這只是報文的頭部,后面的不定長數組Data[ANYSIZE_ARRAY]才是具體的報文。這里ANYSIZE_ARRAY定義為1,其實定義成0也可以,只是表示從這兒開始才是具體的報文內容。具體報文的數據結構可以由使用者自行定義,接收方根據頭部的MessageType就可以知道收到的是什么報文。不過Port機制定義了兩種特殊的報文用于建立連接的過程:

[code]typedef struct _EPORT_CONNECT_REQUEST_MESSAGE
{
  LPC_MESSAGE MessageHeader;
  PEPROCESS ConnectingProcess;
  struct _SECTION_OBJECT* SendSectionObject;
  LARGE_INTEGER SendSectionOffset;
  ULONG SendViewSize;
  ULONG ConnectDataLength;
  UCHAR ConnectData[0];
} EPORT_CONNECT_REQUEST_MESSAGE;[/code]

    這就是“連接請求”報文,其第一個成分是一個LPC_MESSAGE數據結構,那就是報文的頭部。下面的“連接應答”報文也是一樣。前面的參數LpcReply表面上是LPC_MESSAGE指針,但是實際上卻可以是具體報文的指針。注意最后的ConnectData[0]表示在這個數據結構的后面還可以有不定長的數據,報文頭部的DataSize就反映了這部分數據的大小。所以,報文頭部的Data[ANYSIZE_ARRAY]實際上是具體報文的正身,而具體報文如“連接請求”中的ConnectData[0]則是隨同具體報文發送的數據。不過這是額外的數據,因為建立連接所必需的信息已經體現在報文正身的各個字段中了。

[code]typedef struct _EPORT_CONNECT_REPLY_MESSAGE
{
  LPC_MESSAGE MessageHeader;
  PVOID SendServerViewBase;
  ULONG ReceiveClientViewSize;
  PVOID ReceiveClientViewBase;
  ULONG MaximumMessageSize;
  ULONG ConnectDataLength;
  UCHAR ConnectData[0];
} EPORT_CONNECT_REPLY_MESSAGE;[/code]

    最后,包括額外數據在內的報文總長度是有限的(256字節),如果是大塊數據就要通過共享緩沖區發送。
    再看上面EiReplyOrRequestPort()的代碼。它先在內核空間分配一個QUEUEDMESSAGE數據結構作為報文的“容器”,再把需要發送的報文拷貝到這個數據結構中。注意這里的LpcReply有可能是從用戶空間傳下來的,相應的緩沖區也在用戶空間,所以需要把它搬到內核空間的緩沖區中。然后,真正的“發送”操作其實只是把這個數據結構掛入目標端口的接收報文隊列中,這是由EiEnqueueMessagePort()完成的。注意這里的LpcpNextMessageId是報文的序號,每次遞增。還要說明,拷貝到QUEUEDMESSAGE數據結構中的只是報文本身,而不包括通過共享內存區傳遞的數據,這正是為什么要使用共享內存區的原因。

    回到NtReplyWaitReceivePortEx()的代碼。由于沒有應答報文要發送,這里直接就通過KeWaitForSingleObject()進入了睡眠等待。當這個線程接收到了報文而被喚醒(在這里我們忽略超時的可能)時,端口的報文隊列里已經有了報文,所以通過EiDequeueMessagePort()從隊列中摘下一個報文的數據結構。如果這是個“連接請求”報文,就把它復制到用戶提供的緩沖區中,代碼中的兩次調用MmCopyToCaller()就是分別復制報文的正身及其所附帶的數據。其實不是“連接請求”報文也要復制,只不過此時只復制報文的正身。
    然后,對于“連接請求”報文,這里還通過EiEnqueueConnectMessagePort()把它掛入端口的ConnectQueueListHead隊列,這是為隨后的“接受連接”操作、即系統調用NtAcceptConnectPort()留下一個參考,后面我們就會看到其作用。
    不過,我們這兒講的只是如果接收到了連接請求就要做些什么操作,但是實際上此刻還沒有客戶方提出連接請求,所以服務方線程只是睡眠等待。

    至此,服務方已經作好了準備,就等著客戶方的連接請求了。如前所述,客戶方通過系統調用NtConnectPort()向命名的連接端口請求連接。注意這里連接的目標就是一個連接端口,而并不指定某個具體的進程。哪一個進程在這個連接端口上執行了NtListenPort()并因此而受到阻塞正在等待,這請求就實際上是發給那個進程(線程)的。
    請求連接的一方對于將來要發送多大的數據量應該是心里有數的。如果數據量不大,那就可以作為附加信息隨同報文(在同一個緩沖區中)一起發送。但是,要是數據量比較大(報文總長大于256字節),那就要通過共享內存區“發送”,因為否則的話一來傳輸效率低下,二來報文緩沖區的大小也不好靜態地安排確定。所以,在期望的發送數據量比較大時要準備好一個共享內存區(Section)用于數據發送。這是要由請求連接的一方、即客戶方做好準備,通過調用參數傳給NtConnectPort()的。為此客戶方要準備好兩個數據結構,就是LPC_SECTION_WRITE和LPC_SECTION_READ,把有關共享內存區的信息填寫在前一個數據結構中,再把指向這兩個數據結構的指針作為參數傳給NtConnectPort()。
    這兩個數據結構的定義為:

[code]typedef struct _LPC_SECTION_WRITE {
ULONG  Length;
HANDLE  SectionHandle;
ULONG  SectionOffset;
ULONG  ViewSize;
PVOID  ViewBase;
PVOID  TargetViewBase;
} LPC_SECTION_WRITE;

typedef struct _LPC_SECTION_READ {
ULONG  Length;
ULONG  ViewSize;
PVOID  ViewBase;
} LPC_SECTION_READ;[/code]

    注意客戶方只提供(和映射)用于它寫入(發送)的共享內存區,而反方向的共享內存區則由服務方提供(和映射)。所以LPC_SECTION_READ數據結構只是用來獲取映射后的結果。
    下面看NtConnectPort()的代碼。

[code]NTSTATUS STDCALL
NtConnectPort (PHANDLE    UnsafeConnectedPortHandle,
        PUNICODE_STRING   PortName,
        PSECURITY_QUALITY_OF_SERVICE Qos,
        PLPC_SECTION_WRITE  UnsafeWriteMap,
        PLPC_SECTION_READ  UnsafeReadMap,
        PULONG    UnsafeMaximumMessageSize,
        PVOID    UnsafeConnectData,
        PULONG    UnsafeConnectDataLength)
{
  . . . . . .

  /* Copy in write map and partially validate. */
  . . . . . .
  /* Handle connection data. */
  . . . . . .
  /* Reference the named port. */
  Status = ObReferenceObjectByName (PortName, 0, NULL, PORT_ALL_ACCESS,
                       LpcPortObjectType, UserMode, NULL, (PVOID*)&NamedPort);
  . . . . . .
  /* Reference the send section object. */
  if (WriteMap.SectionHandle != INVALID_HANDLE_VALUE)
  {
      Status = ObReferenceObjectByHandle(WriteMap.SectionHandle,
                SECTION_MAP_READ | SECTION_MAP_WRITE,
                MmSectionObjectType, UserMode, (PVOID*)&SectionObject, NULL);
      . . . . . .
  }
  else
  {
      SectionObject = NULL;
  }

  /* Do the connection establishment. */
  Status = EiConnectPort(&ConnectedPort, NamedPort, SectionObject, SectionOffset,
             WriteMap.ViewSize, &WriteMap.ViewBase, &WriteMap.TargetViewBase,
             &ReadMap.ViewSize, &ReadMap.ViewBase, &MaximumMessageSize,
             ConnectData, &ConnectDataLength);
  . . . . . .

  /* Do some initial cleanup. */
  if (SectionObject != NULL)
  {
      ObDereferenceObject(SectionObject);
      SectionObject = NULL;
  }
  ObDereferenceObject(NamedPort);
  NamedPort = NULL;

  /* Copy the data back to the caller. */
  . . . . . .

  Status = ObInsertObject(ConnectedPort, NULL, PORT_ALL_ACCESS,
                                  0, NULL, &ConnectedPortHandle);
  . . . . . .
  Status = MmCopyToCaller(UnsafeConnectedPortHandle,
                        &ConnectedPortHandle, sizeof(HANDLE));
  . . . . . .
  if (UnsafeWriteMap != NULL)
  {
      Status = MmCopyToCaller(UnsafeWriteMap,
                        &WriteMap, sizeof(LPC_SECTION_WRITE));
      . . . . . .
  }
  if (UnsafeReadMap != NULL)
  {
      Status = MmCopyToCaller(UnsafeReadMap,
                        &ReadMap, sizeof(LPC_SECTION_READ));
      . . . . . .
  }
  . . . . . .
  return(STATUS_SUCCESS);

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
一本大道久久精品懂色aⅴ| 日韩美女天天操| 国产一区二区三区免费播放| 最新国产精品久久精品| 9191久久久久久久久久久| 成人看片黄a免费看在线| 午夜欧美电影在线观看| 日本一区二区在线不卡| 欧美精选一区二区| 97精品电影院| 国产久卡久卡久卡久卡视频精品| 亚洲午夜国产一区99re久久| 国产日韩一级二级三级| 日韩视频免费直播| 欧美日韩一区二区三区在线| av一区二区不卡| 国产一区二区三区四区五区入口 | 国产亚洲欧美色| 欧美日韩在线不卡| 日本黄色一区二区| 99r国产精品| 成人精品免费看| 国产露脸91国语对白| 日韩av电影天堂| 亚洲第一搞黄网站| 一区二区三区**美女毛片| 中文字幕一区二区视频| 久久精品夜夜夜夜久久| 久久青草国产手机看片福利盒子 | 激情五月激情综合网| 亚洲图片欧美色图| 夜夜亚洲天天久久| 一区二区三区.www| 亚洲一区二区三区自拍| 亚洲免费观看高清| 亚洲欧美综合在线精品| 日韩美女视频19| 一区二区三区四区视频精品免费 | 毛片不卡一区二区| 美日韩一区二区三区| 日韩精品电影在线观看| 日韩国产欧美在线播放| 日韩制服丝袜av| 免费在线观看精品| 国内精品第一页| 国产剧情在线观看一区二区| 国产一区二区三区香蕉| 成人综合婷婷国产精品久久| 成人激情文学综合网| 99久久久精品| 91麻豆精品一区二区三区| 日本高清不卡一区| 欧美日韩国产美女| 在线电影院国产精品| 日韩一卡二卡三卡四卡| 久久综合久久综合亚洲| 中日韩av电影| 亚洲日本电影在线| 亚洲一区欧美一区| 日本麻豆一区二区三区视频| 美女国产一区二区三区| 国产美女在线精品| 国产成人av影院| 一本色道亚洲精品aⅴ| 在线免费精品视频| 日韩一区二区中文字幕| 久久综合av免费| 最新中文字幕一区二区三区| 亚洲国产va精品久久久不卡综合| 免费成人在线网站| 国产综合一区二区| 色婷婷久久久亚洲一区二区三区 | 日韩一区二区在线观看视频| 欧美精品一区二区高清在线观看| 中文一区在线播放| 亚洲国产一区在线观看| 国产真实精品久久二三区| eeuss鲁片一区二区三区| 欧美日韩一级二级| 国产午夜精品久久久久久久| 亚洲欧洲另类国产综合| 日韩av电影天堂| 成人一级片在线观看| 欧美最猛性xxxxx直播| 精品国产免费视频| 亚洲欧美另类久久久精品| 亚洲成a人片在线观看中文| 国产一区二区福利视频| 在线视频一区二区三| 日韩免费高清av| 亚洲啪啪综合av一区二区三区| 天天综合色天天| 99久久精品国产观看| 日韩一级片在线观看| 亚洲激情网站免费观看| 久久69国产一区二区蜜臀| 99精品黄色片免费大全| 日韩精品一区国产麻豆| 日韩伦理电影网| 国产一区二区导航在线播放| 欧美少妇性性性| 国产精品乱人伦| 激情久久五月天| 欧美日精品一区视频| 国产亚洲欧美日韩日本| 日本欧美肥老太交大片| 91蜜桃在线观看| 国产日本欧洲亚洲| 捆绑变态av一区二区三区| 欧洲色大大久久| 亚洲免费观看高清完整版在线观看熊| 久久99精品久久久久久久久久久久| av高清久久久| 国产精品色哟哟| 黄网站免费久久| 日韩视频一区二区在线观看| 亚洲国产一区二区三区青草影视| 91免费观看在线| 中文字幕中文字幕一区| 国产成都精品91一区二区三| 日韩精品一区二区三区视频在线观看| 亚洲综合在线观看视频| 国产成人午夜视频| 精品欧美久久久| 男男视频亚洲欧美| 欧美一级电影网站| 日本vs亚洲vs韩国一区三区二区| 欧美日韩专区在线| 亚洲国产一区二区三区青草影视| 91日韩一区二区三区| 亚洲欧美日韩在线不卡| 99久久国产综合精品女不卡| 欧美极品另类videosde| 国产成人99久久亚洲综合精品| 精品国产一二三区| 久久99精品久久久久久国产越南| 日韩欧美国产一区在线观看| 蜜桃精品在线观看| 精品国产乱码久久久久久浪潮| 免费成人在线网站| 精品999在线播放| 国产一区二区三区久久悠悠色av| 久久久一区二区三区捆绑**| 国产成a人亚洲| 国产精品国产三级国产三级人妇| 91麻豆.com| 亚洲成av人片观看| 日韩视频一区在线观看| 国模冰冰炮一区二区| 欧美国产综合一区二区| 91视频一区二区三区| 亚洲高清不卡在线观看| 91精品国产手机| 国产美女一区二区| 亚洲欧美色一区| 欧美精品乱码久久久久久按摩| 美女视频一区在线观看| 国产亚洲一区二区三区在线观看| 成人精品免费网站| 香蕉成人伊视频在线观看| 日韩一区二区视频| 国产精品自拍网站| 亚洲精品午夜久久久| 日韩一区二区视频| 懂色av噜噜一区二区三区av | 久久成人久久爱| 久久久久久久精| 色综合天天综合网天天看片| 午夜精品123| 欧美精品一区二区三| 91在线观看一区二区| 亚洲电影欧美电影有声小说| 日韩欧美一区在线| av在线这里只有精品| 日韩精品一区第一页| 国产日韩亚洲欧美综合| 欧美性生活影院| 激情丁香综合五月| 亚洲国产毛片aaaaa无费看| 精品国产乱码91久久久久久网站| 成人影视亚洲图片在线| 亚洲成a人v欧美综合天堂下载| 欧美精品一区二区久久婷婷| 91丨porny丨首页| 激情综合色播激情啊| 亚洲欧洲另类国产综合| 337p亚洲精品色噜噜噜| 国产69精品久久99不卡| 午夜精品久久久久久久99樱桃| 国产调教视频一区| 欧美美女黄视频| a美女胸又www黄视频久久| 美女视频一区二区| 亚洲摸摸操操av| 久久综合色8888| 欧美精品久久99| 91丨porny丨国产| 国产成人日日夜夜| 免费欧美在线视频| 亚洲成人免费在线|