六、项目应用

6.1 w800 wifi多热点广告机
Wifi多热点广告机其原理为构造并发送Beacon帧以伪造任意WiFi热点。
阶段一:基本原理
  首先需要搞清楚的是,手机、电脑等支持WiFi的设备,是如何得知周围无线热点的存在的?无线热点(通常就是无线路由器)会周期性地向外发送Beacon帧,中文名为信标帧。信标帧一个最重要的作用就是宣示无线网络的存在(但不仅仅这个作用)。
  信标帧里面包含了该无线热点的一些基本信息,比如ESSID(也就是常说的网络名称,比如上图中的“1.此广告位招租”)、BSSID(接入点的MAC地址)、加密方式(比如开放无密码、WEP加密或者WPA/WPA2加密)、支持的传输速率等等。
  当无线设备接收到信标帧之后,就能得知周围这个接入点的存在。那么,如果我能够构造一个Beacon帧并且发送出去,那么无线设备收到以后也一样会认为存在这么一个热点。那么当我构造很多个Beacon帧,每个帧都宣示一个接入点,并且周期性地发送这些帧,那么无线设备就会以为周边存在很多个接入点。
  这就是伪造任意WiFi热点的基本原理。
  阶段二:熟悉Beacon帧格式
  那么接下来的目标就很明晰了——构造Beacon帧。要构造Beacon帧,就得知道一个Beacon帧的格式。而在给出Beacon帧的格式之前,需要先说明一下802.11管理帧的通用格式:
  格式中每一个字段上面的数字是指该字段占用的字节数,比如Frame Control占用2字节,Destination Address占用6字节等等。
  一、Frame Control,中文名为帧控制字段,占2个字节,各个位的定义如下:
  (1)Protocol字段由两位构成,用以显示该帧所使用的版本号。目前802.11只有一个版本,编号为0。所以Protocol的值是00。
  (2)Type字段由两位构成,Sub type字段由4位构成。802.11帧共有三种类型的帧,分别是管理帧、控制帧与数据帧。而每种类型又分为多种子类型。Beacon帧的Type字段值为00(管理帧),而Sub type字段值为1000。
  (3)To DS位与From DS位用来指示帧的目的地是否为分布式系统,定义如下:

 由于Beacon帧属于管理帧,所以To DS与From DS都是0。
  (4)Mor Fragments位,类似于IP分包的more fragments位。因为802.11帧对负载有长度限制,所以当上层传入很大的数据时,需要分段传送。Beacon帧不需要分段,所以该位为0。
  (5)Retry位。有时需要重传帧,任何重传的帧都要将此位置为1,否则为0。Beacon帧不存在重传的情况,所以该位为0。
  (6)Power Management位。很多无线设备是以电池供电的,比如手机。当没有数据流量时,关闭无线发射器可以延长电池的使用时间。如果无线设备要把该位置为1,那么就意味着这个帧(或者这次数据交换)传送完成之后,无线设备将进入省电模式。由于接入点是不  允许进入省电模式的,所以Beacon帧的该位为0。
  (7)More data位。为了服务处于省电模式中的无线设备,接入点会将那些要传给无线设备的帧加以缓存。如果无线设备从省电模式中醒来之后,收到一个帧中发现该位置1,说明接入点还有更多的缓存的数据要发送给无线设备。如果只是为了伪造Beacon帧的话,那么这一位一直为0即可。
  (8)Protected Frame位如果被置为1的话,则说明该帧是受到链路层安全协议的保护的,比如WEP和WPA/WPA2。Beacon管理帧是不需要加密的,所以为0。
  (9)Order位如果被置位,那么就表明帧进入了严格依次传送模式,不过发送端与接收端必须付出额外的代价。Beacon帧的该位为0。
由此可得,我们构造的Beacon帧的Frame Control字段为0×80 0×00(按图中的顺序就是00000001,00000000,考虑高位在后,那么就是二进制的10000000,00000000,即0×80 0×00)。
  二、Duration字段在802.11帧中用来预约媒介占用时间。简单来说就是,每一个帧都会通过Duration字段来告知所有的无线设备:“我还要占用媒介多长时间!”。Duration字段保障了一系列原子操作不被打断,当然,前提是大家都遵守802.11协议~而Beacon帧属于广播,没有后续数据交互,所以其Duration为0,即0×00 0×00。
  三、Destination Address即为目的地址,为接收端的MAC地址。由于Beacon帧是广播帧,所以目的地址就是广播地址,即FF:FF:FF:FF:FF:FF。
  四、Source Address即为源地址,为发送端的MAC地址。发送端地址通常就是接入点的MAC地址,但是也有例外,比如中间加了一个中继器,那么发送端的MAC地址就是中继器的地址了。
  五、BSSID就是接入点的MAC地址了。
  六、Seq-ID(Sequence Control)字段中文名为顺序控制字段,它的低4位是分段编号,而高12位为顺序编号。帧片段之间的差异在于分段编号。第一个片段的编号为0,其后每个片段的分段编号依次加以,而它们的顺序编号相同。除了最后一个分段,所有分段的More data位都置位。由于Beacon帧通常不分段,所以低4位为0000,高12位为顺序编号。
  七、Frame body即为帧主体。如果该帧是数据帧,那么帧主题就是数据的有效载荷,如果是管理帧,那么通常是各种信息元素(将在下面讲解)。
  八、FCS,中文名帧校验序列,通常就是循环冗余校验码CRC。
  阶段三:熟悉Beacon帧主体Frame Body
  从上面的分析中可以看出,最重要的内容还是包含在Frame body中。管理帧的Frame body有若干信息元素构成。信息元素有固定长度的信息元素与可变长度的信息元素构成。固定长度的信息元素占用的字节数固定,比如Timestamp固定占用8字节。而可变长度的信息元素占用的字节数不确定,比如Beacon帧中表示网络名称的ESSID。信息元素也可分为必选信息元素与可选信息元素,既然我们只是要构造一个符合条件的,那么就从简处理,构造最简的Frame body即可,那么只需要包含必选的四个信息元素即可:Timestamp、Beacon interval、Capability info和SSID。
  一、Timestamp,占用8字节的时间戳可用来同步BSS中的无线设备。BSS的主定时器会定期传送目前已运行的微秒数。当计数器达到最大值时就会从0开始计数。对于长64位、可计数超过58万年的计数器,要从头开始计数,呵呵。
  二、Beacon interval,占用2字节,用来设定Beacon信号之间相隔多少时间单位。时间单位通常缩写为TU,代表1024微秒。Beacon interval通常会被设定为100个TU,大约每0.1秒发送一次Beacon信号。
  三、Capability info共16位,用来告知网络具备何种性能。每一个位各自代表一个标记,对应到网络所具备的某种特殊功能。工作站会使用这些通告数据来判断自己是否支持该BSS所有的功能。未实现性能通告中所有功能的工作站就无法加入该BSS。各位的定义如下(引用自《802.11无线网络权威指南 第二版》):
  (1)ESS置位则表示该网络是一个扩展服务集的基本结构型,也就是接入点通常创建的网络。IBSS与ESS互斥,如果IBSS置位,则该网络是独立基本服务器网络,也就是常说的无线网卡直连。
  (2)CF-Pollable与CF-Poll request为无竞争-轮询位,表示与省电模式相关的功能。工作站从省电模式醒来之后,可以向工作站轮询是否有缓存的帧。Poll即轮询的意思。对于接入点而言,这两位的组合代表的含义如下表:

 (3)Privacy,保密性。如果将Privacy位设定为0,并且接下来没有WPA信息元素,那么该无线网络即为开放无密码。如果将该为设定为1,代表需要使用WEP以维持机密性。
  (4)Short Preamble,短前导码,802.11b规范新增此字段是为了支持高速直接序列扩频物理层。设定为1,代表此网络目前使用短前导码。0代表不使用此选型,并且在该BSS中禁止使用短前导码。802.11g规定使用短前导码,因此在依据802.11g标准所构建的网络中,此字段必须为1。
  (5)PBCC,封包二进制回旋码,802.11b规范新增此字段是为了支持高速直接序列扩频物理层。设定为1,代表此网络目前使用封包二进制回旋码调制机制,0代表不使用此选项并且在该BSS中禁止使用封包二进制回旋码。
  (6)Channel Agility,机动信道转换,此字段加入802.11b规范是为了支持高速直接序列扩频物理层。设定为1,代表此网络使用机动信道转换选项,0代表不使用此选项并且在该BSS中禁止使用机动信道转换。
  (7)Short Slot Time,该选项是802.11g规范新增的,设定为1代表使用较短的时隙。
  (8)DSSS-OFDM,该选项是802.11g规范新增的,设定为1代表使用DSSS-OFDM帧构造。
  如果我们要构造一个最简的Beacon帧,Capability info字段可以设为0×01 0×00,如果要变成WEP加密的,那么就可以设为0×11 0×00,当然,很多选项选不选无所谓。
  四、SSID,服务集标识符,是一个可变长的信息元素,也就是通常说的网络名称。可变长的信息元素的通用格式为:
  而SSID的Element ID是0。有些文档将SSID视为网络名称,因为网管人员通常以字符串来指定SSID。其实,SSID不过是由字节所形成的字符串,用来标示所属网络的BSSID。有些产品要求此字符串必须是以null(即0)结尾的ASCII字符串,虽然标准对此并无特别规范。SSID的长度介于0至32个字节之间。假如要伪造的热点的名词为“hello”,那么这个元素就应该为0,5,’h’,’e’,’l’,’l’,’o’。
  阶段四:编写代码构造Beacon帧
  由此,我们已经弄清了一个最简Beacon帧的每个细节,除了最后的校验码FCS。让我们来总结一下最后的Beacon帧的样子吧~举个例子,我想伪造一个开放的、名为”hello,carrot!”的、接入点MAC地址为ec:17:2f:2d:b6:b8的接入点,那么最简的Beacon帧应该这样:

具体协议实现可查看程序源码:
uint8_t wifipkt[128] = { 0x80, 0x00, 0x00, 0x00,
/4/0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
/10/0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
/16/0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
/22/0xc0, 0x6c,
/24/0x83, 0x51, 0xf7, 0x8f, 0x0f, 0x00, 0x00, 0x00,
/32/0x56, 0x00,
/34/0x01, 0x04,
/* SSID /
/
36*/0x00
};

uint8_t pktsuffix[] = {
0x01, 0x08, 0x82, 0x84,
0x8b, 0x96, 0x24, 0x30, 0x48, 0x6c, 0x03, 0x01,
0x04
};

void beacon_spam_init()
{
//close station mode
if (tls_wifi_get_listen_mode() != 0)
{
tls_wifi_set_listen_mode(0);
}

//set to station mode
uint8_t wmode;
int ret = tls_param_get(TLS_PARAM_ID_WPROTOCOL, (void *) &wmode, (bool) 0);
if (ret != 0)
{
    printf("tls_param_get ERROR !
");
}
if (wmode != IEEE80211_MODE_INFRA)
{
    wmode = IEEE80211_MODE_INFRA;
    ret = tls_param_set(TLS_PARAM_ID_WPROTOCOL, (void *) &wmode, (bool) 0);
}

//get chip mac
uint8_t *mac = NULL;
mac = wpa_supplicant_get_mac();
if (mac != NULL)
{
    if ((mac[0] != 0xff) && (mac[0] != 0x00))
    {
        memcpy(mac_temp, mac, 6);
        srand(mac_temp[5]);
        mac_temp[4] = rand()/256;
    }
    else
    {
        printf("tls_get_mac_addr: %02x%02x%02x%02x%02x%02x ! ! 
", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
    }
}
else
{
    printf("tls_get_mac_addr err !
");
}

}

static void beacon_spam_handle(void *ptmr, void *parg)
{
static uint8_t rnd = 0;
uint8_t i = 0;

wifipkt[10] = wifipkt[16] = mac_temp[0];
wifipkt[11] = wifipkt[17] = mac_temp[1];
wifipkt[12] = wifipkt[18] = mac_temp[2];
wifipkt[13] = wifipkt[19] = mac_temp[3];
wifipkt[14] = wifipkt[20] = mac_temp[4];
wifipkt[15] = wifipkt[21] = rnd + 0x10;

// printf("rnd: %d ", rnd);
// printf("MAC: %02X%02X%02X%02X%02X%02X ", wifipkt[10], wifipkt[11], wifipkt[12], wifipkt[13], wifipkt[14], wifipkt[15]);
count = 37;
wifipkt[count++] = strlen(ssids[rnd]);

for (i = 0; i < strlen(ssids[rnd]); i++)
{
    wifipkt[count++] = ssids[rnd][i];
}

for (i = 0; i < sizeof(pktsuffix); i++)
{
    wifipkt[count++] = pktsuffix[i];
}

channel = channel_list[rnd];
tls_wifi_change_chanel(channel - 1);

wifipkt[count - 1] = channel;
int ret = tls_wifi_send_data(NULL, wifipkt, count, NULL);
if (ret != 0)
{
    printf("send err : %d
", ret);
}

if (++rnd >= maxssids)
    rnd = 0;

}

程序编译并下载到开发板运行,可以搜素到开发板产生的热点:

原文地址:https://www.cnblogs.com/doiting/p/14109250.html