攔截LPC監控服務載入和啟動

2021-06-06 23:49:54 字數 4363 閱讀 8873

ssdt上hook ntsetsysteminformation ntloaddriver,可以攔截應用層裝載驅動的操作.如果怕不保險,還可以pssetloadimagenotifyroutine或者hook ntcreatesection。但是常規通過服務api載入驅動時卻不能找到載入驅動的源程式,psgetcurrentprocess程式已經是services.exe了.

原因是startservice這個api將服務的相關資訊傳送給了services.exe,services.exe內部統一管理登錄檔中的服務資訊資料,其中就包括啟動乙個驅動服務。想要攔截這個操作需要攔截傳送訊息的native api,就是程序間通訊機制lpc相關的api。

看了幾個開源主防都沒有怎麼去處理,有人直接先在loadimagenotifyroutine裡面記錄載入最後乙個advapi.dll的程序,然後在ntloaddriver裡面判斷當前程序如果是services.exe就直接替換成lastloadadvapiprocess。

查了點資料,都說的不是太細,自己研究了下,only 4 xp。

一.服務載入驅動**

sc_handle hscm = openscmanager(null,null, sc_manager_all_access);

m_hservices =::openservice(hscm,rm_serv_name, service_all_access);

if (m_hservices== null)

if(!startservice(m_hservices,0,0))

……

攔截的時候主要就是上面三個api

二.service.exe的資料結構和基本流程

sc_handle 有三種:

openscmanager返回管理器物件(scmanagerobject),是乙個sc_handle_struct

typedef struct  _sc_handle_struct scmanagerobject;

struct scserviceobject;

} type;

} sc_handle_struct, *lpsc_handle_struct;

service.exe全域性有乙個servicerecord list鍊錶

typedef struct_service_record ;

service_status servicestatus; // see winsvc.h

dword starttype; // auto, demand, etc.

dword errorcontrol; // normal, severe, etc.

dword tag; // dwordid for the service,0=none.

lpdepend_record startdepend;

lpdepend_record stopdepend;

lpwstr dependencies;

psecurity_descriptor servicesd;

dword starterror;

dword startstate;

lpload_order_group memberofgroup;

lpload_order_group registrygroup;

} service_record, *pservice_record,*lpservice_record;

createserviceandopenservice返回的是乙個已經安裝的物件的結構(scserviceobject),官方稱之為context handle,結構是sc_rpc_handle,實際上也是sc_handle_struct

services的啟動時,讀取登錄檔controlset,建立兩個表,第乙個是按照服務group劃分的**,第二個便是服務鍊錶(service record list)。最後將開機自啟動的服務啟動。service.exe還建立乙個rpc server,其他程序需要進行服務管理的操作時便會與其通訊。

三.程序通過startservice載入服務

這個函式在advapi32.dll中,是乙個rpc操作

client_call_return__stdcall rstartservicea(sc_handle hservice, dword dwnumserviceargs, lpcstr*lpserviceargvectors)

ndrclientcall2是乙個rpc通訊函式,位於rpct4.dll,跳過rpc在應用層封裝的一些結構

直接跟到ssdt ndrclientcall2- ndrsendreceive- i_rpcsendreceive- lrpc_ccall::sendreceive(struct _rpc_message *)

.text:77e5c661                 push    eax

.text:77e5c662 push eax

.text:77e5c663 mov eax, [ebx+8ch]

.text:77e5c669 push dword ptr [eax+78h]

.text:77e5c66c call ds:__imp__ntrequestwaitreplyport@12 ;ntrequestwaitreplyport(x,x,x)

來到ssdt的呼叫介面

ntstatus

ntrequestwaitreplyport (

__inhandleporthandle,

__inpport_messagerequestmessage,

__outpport_messagereplymessage

)

lpc本地過程呼叫,是一種程序間通訊機制,c\s模型,面向埠物件。相互像對方埠佇列投遞訊息報文進行通訊,設計思路有點像視窗報文。

ntrequestwaitreplyport目的石頭裡乙個訊息並且接受返回資訊,porthandle是自己埠物件。

typedefstruct_lpcp_port_objectlpcp_port_object, *plpcp_port_object;
過濾時比較主要的就是connectionport,這裡面指向的是對方埠物件,得到對方埠物件後查詢物件名,services建立的服務埠名是 \rpc control\ntsvcs

傳送的訊息是乙個requestmessage結構,解析這個結構能得到通訊資料。

typedefstruct _port_message  s1;

ulong length;

} u1;

union s2;

ulong zeroinit;

} u2;

……}port_message, *pport_message;

typedefstruct _port_data_information port_data_information, *pport_data_information;

typedefstruct _port_data_entry port_data_entry, *pport_data_entry;

有了這些資訊就可以獲取到通訊資訊了,接下來要分析附加的資料,startservices是不能直接得到服務名的,另外兩個api的緩衝區裡面都有,截獲的資料如圖

資料中偏移不是死的,字串按照四位元組對齊後加上乙個偏移值才是下乙個字串

最終效果:

pdf版:

參考:scm 之zwrequestwaitreplyport攔截疑問

lpc communication

關於LPC2200啟動程式分散載入描述檔案的敘述

在ads lpc2200的啟動模板中有乙個scf資料夾,其中有mem a.scf mem b.scf mem c.scf這3個檔案,這3個檔案是ads的分散載入機制,其目的是將 段和資料段分別定位到制定位址上。可以在arm linker中選擇載入路徑。分散裝在技術概述 分散裝在技術可以把使用者的應用...

關於LPC2200啟動程式分散載入描述檔案的敘述

在ads lpc2200的啟動模板中有乙個scf資料夾,其中有mem a.scf mem b.scf mem c.scf這3個檔案,這3個檔案是ads的分散載入機制,其目的是將 段和資料段分別定位到制定位址上。可以在arm linker中選擇載入路徑。分散裝在技術概述 分散裝在技術可以把使用者的應用...

supervise 用來監控服務,自動啟動

atong介紹的這個工具,挺好用的。supervise 官方 cd data test cat test.c include include include int main return 0 cat run bin bash test 執行命令 svstat data test,結果如下 建立服務...