Wifi 嗅探器,便宜又简单

· 7min · Juicecat

简介

WiFi 背后的物理原理

Wifi 嗅探器的存在时间与 Wifi 本身一样长。这个概念很简单——想象一下你在黑暗中有一盏灯笼。它在其周围 360 度半径范围内发光,其附近的任何人都能够看到光。现在,想象一下灯笼发出的光是不可见的,并且可以穿过固体:这正是 WiFi 信号,尽管过于简单化了。

事实上,wifi 信号是电磁辐射 (EMR) 的一种形式,与光、X 射线甚至热灯一样。它的相对较低的频率使其能够渗透固体物体,否则如果您和接入点之间有一堵墙,您将无法连接到您的 WiFi。

1

概念

由于信息是通过这些 WiFi 信号交换的,因此这引起了潜在的恶意行为者或只是好奇的个人的兴趣。利用常用的硬件和对该主题的最少了解,就可以捕获和记录附近的任何和所有 WiFi 信号 - 这就是我们今天要探索的内容。

准备工作

材料

为了制作我们的 wifi 嗅探器,我们只需要一台可以访问 wifi 的计算机,并有一个能够进入混杂模式的适配器。在我的last post中,我介绍了乐鑫的“迷你电脑”SoC ESP32。这些产品非常便宜、体积小且功能强大。您可以花费大约 7 美元购买一个 here

软件

为了编写嗅探器,我们将使用 esp-idf 工具链 (refer to this post to see why)。我使用 VSCode IDE 作为我的文本编辑器,但你使用什么编辑器是个人喜好,没有什么区别。

编写代码

这个项目的代码非常简单,只是一个 PoC,所以它是最小的并且没有那么有用。在 esp-idf 项目中,我们从 app_main() 函数的入口点开始。在我们做任何事情之前,我们需要执行一些先决设置步骤以初始化 wifi 和回调方法: 1.启动esp32事件循环 2. 初始化NVS闪存 3. 初始化网络接口 4.配置网络接口

步骤 1 和 2

对于此类项目来说,这些步骤非常简单且相当标准 - 这是代码,我将在下面进行解释。请记住,这一切都包含在我们的入口点函数中。

ESP_ERROR_CHECK(esp_event_loop_create_default());

  esp_err_t ret = nvs_flash_init();
  if (ret == ESP_ERR_NVS_NO_FREE_PAGES ||
      ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
    ESP_ERROR_CHECK(nvs_flash_erase());
    ret = nvs_flash_init();
  }
  ESP_ERROR_CHECK(ret);

第 1 步完全包含在第 1 行的一行代码中 - 其余部分是初始化 NVS 闪存。这里有一个条件检查,如果出现错误,则会擦除闪存并尝试再次初始化。您在这段代码片段中看到的 ESP_ERROR_CHECK() 函数是一个内置函数,它接受返回代码,如果返回代码是除成功之外的任何内容,则会抛出错误。

步骤 3 和 4

现在我们已经准备好使用 esp32,我们需要设置网络组件。我将这些步骤提取到一个单独的函数中,该函数只是从主函数中调用,以便更好地组织代码:

static void setup_wifi(void) {
  // Initializ
  ESP_LOGI(TAG, "Beginning wifi setup");
  ESP_ERROR_CHECK(esp_netif_init());
  // Interface defaults
  esp_netif_t *sta_netif = esp_netif_create_default_wifi_sta();
  assert(sta_netif);
  // Default config
  wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
  ESP_ERROR_CHECK(esp_wifi_init(&cfg));
  esp_wifi_set_ps(WIFI_PS_MAX_MODEM);
  ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));
  
  // Setup callback
  wifi_promiscuous_cb_t callback = &wifi_callback;
  ESP_ERROR_CHECK(esp_wifi_set_promiscuous_rx_cb(callback));
  
  // Set station mode and start
  ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
  ESP_ERROR_CHECK(esp_wifi_start());

  // Config filters and stuff
  wifi_promiscuous_filter_t filter = {.filter_mask =
                                          WIFI_PROMIS_FILTER_MASK_MGMT};

  esp_wifi_set_promiscuous_filter(&filter);
  ESP_ERROR_CHECK(esp_wifi_set_promiscuous(true));
  ESP_LOGI(TAG, "Wifi started successfully");
  wifi_mode_t ptr;
  ESP_ERROR_CHECK(esp_wifi_get_mode(&ptr));
  const char *c = wifi_mode_to_string(ptr);
  ESP_LOGI(TAG, "Mode: %s", c);

}

为了实际使用这些数据包,我们需要创建一个回调函数,每当捕获与过滤器匹配的帧时就会调用该函数,我们在第 15-16 行执行此操作。

在第 23 行,我设置了一个过滤器以仅捕获管理帧,这只是某种类型的消息 - 我这样做没有任何原因,只是为了减少该程序产生的噪音,否则每秒将有数千个数据包到达接口。这段代码是相当不言自明的,但您可能会注意到我调用了一个名为 wifi_mode_to_string 的函数。这是因为 wifi_mode_t 成员是一个枚举,而伟大的 C 语言无法打印出枚举的字符串表示形式,因此我们必须手动映射它:

const char *wifi_mode_to_string(wifi_mode_t mode) {
  switch (mode) {
  case WIFI_MODE_NULL:
    return "WIFI_MODE_NULL";
  case WIFI_MODE_STA:
    return "WIFI_MODE_STA";
  case WIFI_MODE_AP:
    return "WIFI_MODE_AP";
  case WIFI_MODE_APSTA:
    return "WIFI_MODE_APSTA";
  case WIFI_MODE_NAN:
    return "WIFI_MODE_NAN";
  case WIFI_MODE_MAX:
    return "WIFI_MODE_MAX";
  default:
    return "UNKNOWN_MODE";
  }
}

把它们放在一起

现在一切都已设置完毕,我们只需要创建 wifi 回调函数并记录我们获得的数据。在我们的回调函数中,由于这是一个 PoC,所以除了打印帧之外我们不需要做任何事情 -

void wifi_callback(void *buf, wifi_promiscuous_pkt_type_t type) {
  const uint16_t data_length = 256;
  ESP_LOGI(TAG, "Printing first %d bytes of received packet with type %s\n",
           data_length, wifi_pkt_type_to_string(type));
  unsigned char *char_buf = (unsigned char *)buf;
  
  for (int i = 0; i < data_length; i++) {
    printf("%02X ", char_buf[i]); // 1 byte = 0x00, two hex chars
    if (i % 16 == 15) { // Organize it by groups of 16 bytes because im spoiled by wireshark
      printf("\n");
    }
  }
}

执行中

现在,我们只需导航到项目工作目录并构建项目,编译它,将其刷新到 ESP32,最后建立 UART 连接,以便我们可以看到输出。我们可以用一个简单的命令来做到这一点: idfx build && idfx flash COM11 monitor

输出如下 - 1

结论

正如一开始所指出的,这只是一个 PoC,并且 不是 在任何实际方面都非常有用。为此目的已经构建了一些成熟且出色的工具,例如 WiresharkAir*-ng suite

这篇文章的目的是提供一个简单的解释和概述,说明什么是 wifi 嗅探,以及它是如何轻松完成的。因此,我希望我能够很好地解释事情——我不擅长写博客文章,但我正在努力改进,所以请耐心等待。