普段私たちが使っているWi-Fiは、"IEEE802.11" という規格に基づいて通信が行われます。 そして、AP (アクセスポイント) を認識させるには、ビーコンフレームを使います。
ビーコンフレームは、ネットワークの存在を通知します。私たちが普段Wi-Fi接続するときに、SSID (ネットワーク名) を確認しますが、これはビーコンフレームの中に含まれています。端末がビーコンフレームをキャッチすれば、そのAPが展開するネットワークに参加するチャンスがあるわけです。しかし厳密には、APが指定する機能を全て、端末は実装している必要があります。今回はどの端末でも参加できるような、とても簡易的なAPを作成します。あくまで疑似なので、ビーコンを送信して、疑似APの存在を端末側で確認するのみとします。実際に作成した疑似APに接続して、通信を行えるようにする(実装)には、時間がかかりそうだったので折れました。

IEEE802.11のビーコンフレームも、他の無線規格同様に、フォーマットが定められています。実際は、Wi-Fiを含め、IEEE802.11規格を使った通信には、ビーコンフレーム以外にも、たくさんの種類があります。IEEE802.11通信にはデータの種類に応じて、大きく3種類のフレームタイプに区別することが出来ます。
- マネジメントフレーム (ビーコン / プローブ要求 / プローブ応答 など)
- コントロールフレーム (RTS / CTS/ ACK など)
- データフレーム (レイヤ3以上のデータを運ぶ)
3つのフレームタイプの中でも、さらに細かく分けることが出来ます。全てを理解するには、IEEE802.11の通信が実際にどのように動いているかを勉強する必要があります。今回はマネジメントフレームの中のビーコンフレームを実装していきます。
IEEE802.11 MAC層はフレームタイプによって、フォーマットも少し変わります。とはいえど、基本的な構造は同じです。

IEEE802.11 MAC層の最初にあるフィールド "フレームコントロール" によって、このパケットはどのフレームタイプなのかを識別します。そして、フレームタイプによって、MACヘッダーが少し変わります。MAC層ペイロードのところで、各フレームに応じたデータが入ります。
マネジメントフレームのフォーマットは以下になっています。

他のフレームタイプも、MAC層基本フォーマットをもとに、少しフォーマットが変わります。今回はビーコンを送信するので、このマネジメントフレームのフォーマットに基づいて実装します。 そして、ビーコンフレームに限ったことではありませんが、マネジメントフレームのペイロード部分には、固定フィールド (Fixed Field) と 情報エレメント (Infromation Element) と呼ばれる2種類のデータが入ります。例えば以下のものがあります。
- ビーコン間隔 (Beacon Interval)
- タイムスタンプ (Timestamp)
- ケーパビリティ情報 (Capability Information)
- SSID
- サポートレート (Supported Rates)
- DSパラメータセット (DS Parameter Set)
今あげたものは、ビーコンフレームでよく使われるデータですが、これはペイロードに入るデータ種類の一部に過ぎません。
上の3つは、固定フィールドと呼ばれるあらかじめデータ長が決まっているデータです。一方で下3つは、情報エレメントと呼ばれる、データ値によってデータ長が変わる可変フィールドです。情報エレメントのイメージはオプションみたいなもので、種類がたくさんあり、その種類に応じて、エレメントIDが割り振られています。
それでは各データについて、簡単に説明します。
ビーコン間隔 (Beacon Interval)は、2バイトのフィールドで指定します。伝送間隔は "タイムユニット" と呼ばれる単位で指定され、1タイムユニットは1,024 μ秒を表しています (約1ミリ秒) 。一般的にはこのビーコン間隔に、100タイムユニットがセットされ、約0.1秒ごとビーコンが送信されます。
タイムスタンプ (Timestamp)は、同期を実現するためのもので、4バイトのフィールドです。APが立ち上がってから、カウントが始ります。64ビットなので、 フルカウントになるまで、最低580,000年以上必要です。なので実際のところは、無限にカウントできると思っても良いかと思います。プログラム上では、最初に0を指定して、時間を取得しなければいけませんが、簡素化のためそこまでは行っていません。
ケーパビリティ情報 (Capability Information)は、2バイトにビット単位フィールドで、各ビットがネットワークの特定の機能を通知するフラグとして使われます。ビーコンだけでなく、プローブ要求やプローブ応答でも使用されます。APが指定したケーパビリティ情報を実装していない端末は、そのAPに接続することが出来ません。今回は簡易的なAPなので、ほぼ全てのビットに0をセットしますが、APはケーパビリティ情報の1ビット目 (ESSフィールド) は、1をセットする必要があります。
サポートレート (Supported Rates)は、データレートのことです。データレートはサポート必須のものと必須でないものがあります。APが飛ばしたビーコンに、データレートを指定し、端末はそのAPが展開するネットワークに入りたければ、必須となっているデータレートはサポートしている必要があります。APが必須といっているデータレートをサポートしていない端末は、ネットワークに参加できません。サポートレートのエレメントIDは1です。データレート対応表に一部を併せて載せておきます。サポートするデータレートの数だけ、"サポートレート"全体のデータ長は増えます。ソースでは、IEEE802.11bのデータレートをサポートしてあります。

SSIDは、ネットワーク名を示します。最大で32文字まで、名前を決めることが出来ます。指定したSSIDの文字数の数だけ、データ長が増えます。エレメントIDは0です。以下のソースではSSID名を "Hello World!" としました。
DSパラメータセット (DS Parameter Set)は、ネットワーク使うチャネル番号を入れます。エレメントIDは3です。
引用:
英語で書かれていますが、IEEE802.11フレームの各フィールドについて説明されているので、良かったら参考にしてみて下さい。
https://www.oreilly.com/library/view/80211-wireless-networks/0596100523/ch04.html
ソースは以下のようになっています。
IEEE802.11フレームをCで送信するためのコード
ieee80211.hは標準では定義されていませんので、自分で用意します。有志が作ったものがありますが、量が少し多いので、ビーコンを送信するにあたって、必要な箇所だけ抜粋しました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 |
/*ieee80211.h*/ #include<sys/socket.h> #include<linux/if_ether.h> #include<netinet/in.h> #define FCS_LEN 4 /*Frame Control MASK*/ #define IEEE80211_FCTL_VERS 0x0003 //00000000 00000011 #define IEEE80211_FCTL_FTYPE 0x000c //00000000 00001100 #define IEEE80211_FCTL_STYPE 0x00f0 //00000000 11110000 #define IEEE80211_FCTL_TODS 0x0100 //00000001 00000000 #define IEEE80211_FCTL_FROMDS 0x0200 //00000010 00000000 #define IEEE80211_FCTL_MOREFRAGS 0x0400 //00000100 00000000 #define IEEE80211_FCTL_RETRY 0x0800 //00001000 00000000 #define IEEE80211_FCTL_PM 0x1000 //00010000 00000000 #define IEEE80211_FCTL_MOREDATA 0x2000 //00100000 00000000 #define IEEE80211_FCTL_PROTECTED 0x4000 //01000000 00000000 #define IEEE80211_FCTL_ORDER 0x8000 //10000000 00000000 #define IEEE80211_FCTL_CTL_EXT 0x0f00 //00001111 00000000 #define IEEE80211_SCTL_FRAG 0x000F #define IEEE80211_SCTL_SEQ 0xFFF0 /*Frame Control Frame Type*/ #define IEEE80211_FTYPE_MGMT 0x0000 //00 #define IEEE80211_FTYPE_CTL 0x0004 //01 #define IEEE80211_FTYPE_DATA 0x0008 //10 #define IEEE80211_FTYPE_EXT 0x000c //11 /* management subtype */ #define IEEE80211_STYPE_ASSOC_REQ 0x0000 #define IEEE80211_STYPE_ASSOC_RESP 0x0010 #define IEEE80211_STYPE_REASSOC_REQ 0x0020 #define IEEE80211_STYPE_REASSOC_RESP 0x0030 #define IEEE80211_STYPE_PROBE_REQ 0x0040 #define IEEE80211_STYPE_PROBE_RESP 0x0050 #define IEEE80211_STYPE_BEACON 0x0080 #define IEEE80211_STYPE_ATIM 0x0090 #define IEEE80211_STYPE_DISASSOC 0x00A0 #define IEEE80211_STYPE_AUTH 0x00B0 #define IEEE80211_STYPE_DEAUTH 0x00C0 #define IEEE80211_STYPE_ACTION 0x00D0 /* IEEE802.11 MAC Header (Managment Frame)*/ struct ieee80211_frame { uint16_t i_fc; uint16_t i_dur; uint8_t i_addr1[ETH_ALEN]; uint8_t i_addr2[ETH_ALEN]; uint8_t i_addr3[ETH_ALEN]; uint16_t seq_ctrl; }; enum ieee80211_eid { IEEE80211_ELEMID_SSID = 0, IEEE80211_ELEMID_RATES = 1, WLAN_EID_FH_PARAMS = 2, /* reserved now */ IEEE80211_ELEMID_DSPARAMS = 3, WLAN_EID_CF_PARAMS = 4, WLAN_EID_TIM = 5, WLAN_EID_IBSS_PARAMS = 6, WLAN_EID_COUNTRY = 7, /* 8, 9 reserved */ WLAN_EID_REQUEST = 10, WLAN_EID_QBSS_LOAD = 11, WLAN_EID_EDCA_PARAM_SET = 12, WLAN_EID_TSPEC = 13, WLAN_EID_TCLAS = 14, WLAN_EID_SCHEDULE = 15, WLAN_EID_CHALLENGE = 16, /* 17-31 reserved for challenge text extension */ WLAN_EID_PWR_CONSTRAINT = 32, WLAN_EID_PWR_CAPABILITY = 33, WLAN_EID_TPC_REQUEST = 34, WLAN_EID_TPC_REPORT = 35, WLAN_EID_SUPPORTED_CHANNELS = 36, WLAN_EID_CHANNEL_SWITCH = 37, WLAN_EID_MEASURE_REQUEST = 38, WLAN_EID_MEASURE_REPORT = 39, WLAN_EID_QUIET = 40, WLAN_EID_IBSS_DFS = 41, WLAN_EID_ERP_INFO = 42, WLAN_EID_TS_DELAY = 43, WLAN_EID_TCLAS_PROCESSING = 44, WLAN_EID_HT_CAPABILITY = 45, WLAN_EID_QOS_CAPA = 46, /* 47 reserved for Broadcom */ WLAN_EID_RSN = 48, WLAN_EID_802_15_COEX = 49, WLAN_EID_EXT_SUPP_RATES = 50, WLAN_EID_AP_CHAN_REPORT = 51, WLAN_EID_NEIGHBOR_REPORT = 52, WLAN_EID_RCPI = 53, WLAN_EID_MOBILITY_DOMAIN = 54, WLAN_EID_FAST_BSS_TRANSITION = 55, WLAN_EID_TIMEOUT_INTERVAL = 56, WLAN_EID_RIC_DATA = 57, WLAN_EID_DSE_REGISTERED_LOCATION = 58, WLAN_EID_SUPPORTED_REGULATORY_CLASSES = 59, WLAN_EID_EXT_CHANSWITCH_ANN = 60, WLAN_EID_HT_OPERATION = 61, WLAN_EID_SECONDARY_CHANNEL_OFFSET = 62, WLAN_EID_BSS_AVG_ACCESS_DELAY = 63, WLAN_EID_ANTENNA_INFO = 64, WLAN_EID_RSNI = 65, WLAN_EID_MEASUREMENT_PILOT_TX_INFO = 66, WLAN_EID_BSS_AVAILABLE_CAPACITY = 67, WLAN_EID_BSS_AC_ACCESS_DELAY = 68, WLAN_EID_TIME_ADVERTISEMENT = 69, WLAN_EID_RRM_ENABLED_CAPABILITIES = 70, WLAN_EID_MULTIPLE_BSSID = 71, WLAN_EID_BSS_COEX_2040 = 72, WLAN_EID_BSS_INTOLERANT_CHL_REPORT = 73, WLAN_EID_OVERLAP_BSS_SCAN_PARAM = 74, WLAN_EID_RIC_DESCRIPTOR = 75, WLAN_EID_MMIE = 76, WLAN_EID_ASSOC_COMEBACK_TIME = 77, WLAN_EID_EVENT_REQUEST = 78, WLAN_EID_EVENT_REPORT = 79, WLAN_EID_DIAGNOSTIC_REQUEST = 80, WLAN_EID_DIAGNOSTIC_REPORT = 81, WLAN_EID_LOCATION_PARAMS = 82, WLAN_EID_NON_TX_BSSID_CAP = 83, WLAN_EID_SSID_LIST = 84, WLAN_EID_MULTI_BSSID_IDX = 85, WLAN_EID_FMS_DESCRIPTOR = 86, WLAN_EID_FMS_REQUEST = 87, WLAN_EID_FMS_RESPONSE = 88, WLAN_EID_QOS_TRAFFIC_CAPA = 89, WLAN_EID_BSS_MAX_IDLE_PERIOD = 90, WLAN_EID_TSF_REQUEST = 91, WLAN_EID_TSF_RESPOSNE = 92, WLAN_EID_WNM_SLEEP_MODE = 93, WLAN_EID_TIM_BCAST_REQ = 94, WLAN_EID_TIM_BCAST_RESP = 95, WLAN_EID_COLL_IF_REPORT = 96, WLAN_EID_CHANNEL_USAGE = 97, WLAN_EID_TIME_ZONE = 98, WLAN_EID_DMS_REQUEST = 99, WLAN_EID_DMS_RESPONSE = 100, WLAN_EID_LINK_ID = 101, WLAN_EID_WAKEUP_SCHEDUL = 102, /* 103 reserved */ WLAN_EID_CHAN_SWITCH_TIMING = 104, WLAN_EID_PTI_CONTROL = 105, WLAN_EID_PU_BUFFER_STATUS = 106, WLAN_EID_INTERWORKING = 107, WLAN_EID_ADVERTISEMENT_PROTOCOL = 108, WLAN_EID_EXPEDITED_BW_REQ = 109, WLAN_EID_QOS_MAP_SET = 110, WLAN_EID_ROAMING_CONSORTIUM = 111, WLAN_EID_EMERGENCY_ALERT = 112, WLAN_EID_MESH_CONFIG = 113, WLAN_EID_MESH_ID = 114, WLAN_EID_LINK_METRIC_REPORT = 115, WLAN_EID_CONGESTION_NOTIFICATION = 116, WLAN_EID_PEER_MGMT = 117, WLAN_EID_CHAN_SWITCH_PARAM = 118, WLAN_EID_MESH_AWAKE_WINDOW = 119, WLAN_EID_BEACON_TIMING = 120, WLAN_EID_MCCAOP_SETUP_REQ = 121, WLAN_EID_MCCAOP_SETUP_RESP = 122, WLAN_EID_MCCAOP_ADVERT = 123, WLAN_EID_MCCAOP_TEARDOWN = 124, WLAN_EID_GANN = 125, WLAN_EID_RANN = 126, WLAN_EID_EXT_CAPABILITY = 127, /* 128, 129 reserved for Agere */ WLAN_EID_PREQ = 130, WLAN_EID_PREP = 131, WLAN_EID_PERR = 132, /* 133-136 reserved for Cisco */ WLAN_EID_PXU = 137, WLAN_EID_PXUC = 138, WLAN_EID_AUTH_MESH_PEER_EXCH = 139, WLAN_EID_MIC = 140, WLAN_EID_DESTINATION_URI = 141, WLAN_EID_UAPSD_COEX = 142, WLAN_EID_WAKEUP_SCHEDULE = 143, WLAN_EID_EXT_SCHEDULE = 144, WLAN_EID_STA_AVAILABILITY = 145, WLAN_EID_DMG_TSPEC = 146, WLAN_EID_DMG_AT = 147, WLAN_EID_DMG_CAP = 148, /* 149 reserved for Cisco */ WLAN_EID_CISCO_VENDOR_SPECIFIC = 150, WLAN_EID_DMG_OPERATION = 151, WLAN_EID_DMG_BSS_PARAM_CHANGE = 152, WLAN_EID_DMG_BEAM_REFINEMENT = 153, WLAN_EID_CHANNEL_MEASURE_FEEDBACK = 154, /* 155-156 reserved for Cisco */ WLAN_EID_AWAKE_WINDOW = 157, WLAN_EID_MULTI_BAND = 158, WLAN_EID_ADDBA_EXT = 159, WLAN_EID_NEXT_PCP_LIST = 160, WLAN_EID_PCP_HANDOVER = 161, WLAN_EID_DMG_LINK_MARGIN = 162, WLAN_EID_SWITCHING_STREAM = 163, WLAN_EID_SESSION_TRANSITION = 164, WLAN_EID_DYN_TONE_PAIRING_REPORT = 165, WLAN_EID_CLUSTER_REPORT = 166, WLAN_EID_RELAY_CAP = 167, WLAN_EID_RELAY_XFER_PARAM_SET = 168, WLAN_EID_BEAM_LINK_MAINT = 169, WLAN_EID_MULTIPLE_MAC_ADDR = 170, WLAN_EID_U_PID = 171, WLAN_EID_DMG_LINK_ADAPT_ACK = 172, /* 173 reserved for Symbol */ WLAN_EID_MCCAOP_ADV_OVERVIEW = 174, WLAN_EID_QUIET_PERIOD_REQ = 175, /* 176 reserved for Symbol */ WLAN_EID_QUIET_PERIOD_RESP = 177, /* 178-179 reserved for Symbol */ /* 180 reserved for ISO/IEC 20011 */ WLAN_EID_EPAC_POLICY = 182, WLAN_EID_CLISTER_TIME_OFF = 183, WLAN_EID_INTER_AC_PRIO = 184, WLAN_EID_SCS_DESCRIPTOR = 185, WLAN_EID_QLOAD_REPORT = 186, WLAN_EID_HCCA_TXOP_UPDATE_COUNT = 187, WLAN_EID_HL_STREAM_ID = 188, WLAN_EID_GCR_GROUP_ADDR = 189, WLAN_EID_ANTENNA_SECTOR_ID_PATTERN = 190, WLAN_EID_VHT_CAPABILITY = 191, WLAN_EID_VHT_OPERATION = 192, WLAN_EID_EXTENDED_BSS_LOAD = 193, WLAN_EID_WIDE_BW_CHANNEL_SWITCH = 194, WLAN_EID_VHT_TX_POWER_ENVELOPE = 195, WLAN_EID_CHANNEL_SWITCH_WRAPPER = 196, WLAN_EID_AID = 197, WLAN_EID_QUIET_CHANNEL = 198, WLAN_EID_OPMODE_NOTIF = 199, WLAN_EID_VENDOR_SPECIFIC = 221, WLAN_EID_QOS_PARAMETER = 222, WLAN_EID_CAG_NUMBER = 237, WLAN_EID_AP_CSN = 239, WLAN_EID_FILS_INDICATION = 240, WLAN_EID_DILS = 241, WLAN_EID_FRAGMENT = 242, WLAN_EID_EXTENSION = 255 }; |
あと、ieee80211_radiotap.hも使います。"IEEE802.11 Radiotap" とググれば、Radiotapヘッダーについて出てきますが、日本語のサイトはあまりありません。私自身も詳しくは理解しておりません。なので有志が作ったieee80211_radiotap.hは、ほとんど丸ごと使っております。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 |
/*ieee80211_radiotap.h*/ #ifndef __RADIOTAP_H #define __RADIOTAP_H #include<linux/kernel.h> #include<unistd.h> #include<linux/swab.h> #include<asm/types.h> #include<netinet/in.h> #include<stdint.h> #include<sys/ipc.h> #include<sys/shm.h> static inline uint16_t get_unaligned_le16(const void *p) { const uint8_t *_p = p; return _p[0] | _p[1] << 8; } struct ieee80211_radiotap_header { /** * @it_version: radiotap version, always 0 */ uint8_t it_version; /** * @it_pad: padding (or alignment) */ uint8_t it_pad; /** * @it_len: overall radiotap header length */ uint16_t it_len; /** * @it_present: (first) present word */ uint32_t it_present; } __packed; /* version is always 0 */ #define PKTHDR_RADIOTAP_VERSION 0 /* see the radiotap website for the descriptions */ enum ieee80211_radiotap_presence { IEEE80211_RADIOTAP_TSFT = 0, IEEE80211_RADIOTAP_FLAGS = 1, IEEE80211_RADIOTAP_RATE = 2, IEEE80211_RADIOTAP_CHANNEL = 3, IEEE80211_RADIOTAP_FHSS = 4, IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5, IEEE80211_RADIOTAP_DBM_ANTNOISE = 6, IEEE80211_RADIOTAP_LOCK_QUALITY = 7, IEEE80211_RADIOTAP_TX_ATTENUATION = 8, IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9, IEEE80211_RADIOTAP_DBM_TX_POWER = 10, IEEE80211_RADIOTAP_ANTENNA = 11, IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12, IEEE80211_RADIOTAP_DB_ANTNOISE = 13, IEEE80211_RADIOTAP_RX_FLAGS = 14, IEEE80211_RADIOTAP_TX_FLAGS = 15, IEEE80211_RADIOTAP_RTS_RETRIES = 16, IEEE80211_RADIOTAP_DATA_RETRIES = 17, /* 18 is XChannel, but it's not defined yet */ IEEE80211_RADIOTAP_MCS = 19, IEEE80211_RADIOTAP_AMPDU_STATUS = 20, IEEE80211_RADIOTAP_VHT = 21, IEEE80211_RADIOTAP_TIMESTAMP = 22, IEEE80211_RADIOTAP_HE = 23, IEEE80211_RADIOTAP_HE_MU = 24, IEEE80211_RADIOTAP_ZERO_LEN_PSDU = 26, IEEE80211_RADIOTAP_LSIG = 27, /* valid in every it_present bitmap, even vendor namespaces */ IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE = 29, IEEE80211_RADIOTAP_VENDOR_NAMESPACE = 30, IEEE80211_RADIOTAP_EXT = 31 }; /* for IEEE80211_RADIOTAP_FLAGS */ enum ieee80211_radiotap_flags { IEEE80211_RADIOTAP_F_CFP = 0x01, IEEE80211_RADIOTAP_F_SHORTPRE = 0x02, IEEE80211_RADIOTAP_F_WEP = 0x04, IEEE80211_RADIOTAP_F_FRAG = 0x08, IEEE80211_RADIOTAP_F_FCS = 0x10, IEEE80211_RADIOTAP_F_DATAPAD = 0x20, IEEE80211_RADIOTAP_F_BADFCS = 0x40, }; /* for IEEE80211_RADIOTAP_CHANNEL */ enum ieee80211_radiotap_channel_flags { IEEE80211_CHAN_CCK = 0x0020, IEEE80211_CHAN_OFDM = 0x0040, IEEE80211_CHAN_2GHZ = 0x0080, IEEE80211_CHAN_5GHZ = 0x0100, IEEE80211_CHAN_DYN = 0x0400, IEEE80211_CHAN_HALF = 0x4000, IEEE80211_CHAN_QUARTER = 0x8000, }; /* for IEEE80211_RADIOTAP_RX_FLAGS */ enum ieee80211_radiotap_rx_flags { IEEE80211_RADIOTAP_F_RX_BADPLCP = 0x0002, }; /* for IEEE80211_RADIOTAP_TX_FLAGS */ enum ieee80211_radiotap_tx_flags { IEEE80211_RADIOTAP_F_TX_FAIL = 0x0001, IEEE80211_RADIOTAP_F_TX_CTS = 0x0002, IEEE80211_RADIOTAP_F_TX_RTS = 0x0004, IEEE80211_RADIOTAP_F_TX_NOACK = 0x0008, }; /* for IEEE80211_RADIOTAP_MCS "have" flags */ enum ieee80211_radiotap_mcs_have { IEEE80211_RADIOTAP_MCS_HAVE_BW = 0x01, IEEE80211_RADIOTAP_MCS_HAVE_MCS = 0x02, IEEE80211_RADIOTAP_MCS_HAVE_GI = 0x04, IEEE80211_RADIOTAP_MCS_HAVE_FMT = 0x08, IEEE80211_RADIOTAP_MCS_HAVE_FEC = 0x10, IEEE80211_RADIOTAP_MCS_HAVE_STBC = 0x20, }; enum ieee80211_radiotap_mcs_flags { IEEE80211_RADIOTAP_MCS_BW_MASK = 0x03, IEEE80211_RADIOTAP_MCS_BW_20 = 0, IEEE80211_RADIOTAP_MCS_BW_40 = 1, IEEE80211_RADIOTAP_MCS_BW_20L = 2, IEEE80211_RADIOTAP_MCS_BW_20U = 3, IEEE80211_RADIOTAP_MCS_SGI = 0x04, IEEE80211_RADIOTAP_MCS_FMT_GF = 0x08, IEEE80211_RADIOTAP_MCS_FEC_LDPC = 0x10, IEEE80211_RADIOTAP_MCS_STBC_MASK = 0x60, IEEE80211_RADIOTAP_MCS_STBC_1 = 1, IEEE80211_RADIOTAP_MCS_STBC_2 = 2, IEEE80211_RADIOTAP_MCS_STBC_3 = 3, IEEE80211_RADIOTAP_MCS_STBC_SHIFT = 5, }; /* for IEEE80211_RADIOTAP_AMPDU_STATUS */ enum ieee80211_radiotap_ampdu_flags { IEEE80211_RADIOTAP_AMPDU_REPORT_ZEROLEN = 0x0001, IEEE80211_RADIOTAP_AMPDU_IS_ZEROLEN = 0x0002, IEEE80211_RADIOTAP_AMPDU_LAST_KNOWN = 0x0004, IEEE80211_RADIOTAP_AMPDU_IS_LAST = 0x0008, IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR = 0x0010, IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN = 0x0020, IEEE80211_RADIOTAP_AMPDU_EOF = 0x0040, IEEE80211_RADIOTAP_AMPDU_EOF_KNOWN = 0x0080, }; /* for IEEE80211_RADIOTAP_VHT */ enum ieee80211_radiotap_vht_known { IEEE80211_RADIOTAP_VHT_KNOWN_STBC = 0x0001, IEEE80211_RADIOTAP_VHT_KNOWN_TXOP_PS_NA = 0x0002, IEEE80211_RADIOTAP_VHT_KNOWN_GI = 0x0004, IEEE80211_RADIOTAP_VHT_KNOWN_SGI_NSYM_DIS = 0x0008, IEEE80211_RADIOTAP_VHT_KNOWN_LDPC_EXTRA_OFDM_SYM = 0x0010, IEEE80211_RADIOTAP_VHT_KNOWN_BEAMFORMED = 0x0020, IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH = 0x0040, IEEE80211_RADIOTAP_VHT_KNOWN_GROUP_ID = 0x0080, IEEE80211_RADIOTAP_VHT_KNOWN_PARTIAL_AID = 0x0100, }; enum ieee80211_radiotap_vht_flags { IEEE80211_RADIOTAP_VHT_FLAG_STBC = 0x01, IEEE80211_RADIOTAP_VHT_FLAG_TXOP_PS_NA = 0x02, IEEE80211_RADIOTAP_VHT_FLAG_SGI = 0x04, IEEE80211_RADIOTAP_VHT_FLAG_SGI_NSYM_M10_9 = 0x08, IEEE80211_RADIOTAP_VHT_FLAG_LDPC_EXTRA_OFDM_SYM = 0x10, IEEE80211_RADIOTAP_VHT_FLAG_BEAMFORMED = 0x20, }; enum ieee80211_radiotap_vht_coding { IEEE80211_RADIOTAP_CODING_LDPC_USER0 = 0x01, IEEE80211_RADIOTAP_CODING_LDPC_USER1 = 0x02, IEEE80211_RADIOTAP_CODING_LDPC_USER2 = 0x04, IEEE80211_RADIOTAP_CODING_LDPC_USER3 = 0x08, }; /* for IEEE80211_RADIOTAP_TIMESTAMP */ enum ieee80211_radiotap_timestamp_unit_spos { IEEE80211_RADIOTAP_TIMESTAMP_UNIT_MASK = 0x000F, IEEE80211_RADIOTAP_TIMESTAMP_UNIT_MS = 0x0000, IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US = 0x0001, IEEE80211_RADIOTAP_TIMESTAMP_UNIT_NS = 0x0003, IEEE80211_RADIOTAP_TIMESTAMP_SPOS_MASK = 0x00F0, IEEE80211_RADIOTAP_TIMESTAMP_SPOS_BEGIN_MDPU = 0x0000, IEEE80211_RADIOTAP_TIMESTAMP_SPOS_PLCP_SIG_ACQ = 0x0010, IEEE80211_RADIOTAP_TIMESTAMP_SPOS_EO_PPDU = 0x0020, IEEE80211_RADIOTAP_TIMESTAMP_SPOS_EO_MPDU = 0x0030, IEEE80211_RADIOTAP_TIMESTAMP_SPOS_UNKNOWN = 0x00F0, }; enum ieee80211_radiotap_timestamp_flags { IEEE80211_RADIOTAP_TIMESTAMP_FLAG_64BIT = 0x00, IEEE80211_RADIOTAP_TIMESTAMP_FLAG_32BIT = 0x01, IEEE80211_RADIOTAP_TIMESTAMP_FLAG_ACCURACY = 0x02, }; struct ieee80211_radiotap_he { __le16 data1, data2, data3, data4, data5, data6; }; enum ieee80211_radiotap_he_bits { IEEE80211_RADIOTAP_HE_DATA1_FORMAT_MASK = 3, IEEE80211_RADIOTAP_HE_DATA1_FORMAT_SU = 0, IEEE80211_RADIOTAP_HE_DATA1_FORMAT_EXT_SU = 1, IEEE80211_RADIOTAP_HE_DATA1_FORMAT_MU = 2, IEEE80211_RADIOTAP_HE_DATA1_FORMAT_TRIG = 3, IEEE80211_RADIOTAP_HE_DATA1_BSS_COLOR_KNOWN = 0x0004, IEEE80211_RADIOTAP_HE_DATA1_BEAM_CHANGE_KNOWN = 0x0008, IEEE80211_RADIOTAP_HE_DATA1_UL_DL_KNOWN = 0x0010, IEEE80211_RADIOTAP_HE_DATA1_DATA_MCS_KNOWN = 0x0020, IEEE80211_RADIOTAP_HE_DATA1_DATA_DCM_KNOWN = 0x0040, IEEE80211_RADIOTAP_HE_DATA1_CODING_KNOWN = 0x0080, IEEE80211_RADIOTAP_HE_DATA1_LDPC_XSYMSEG_KNOWN = 0x0100, IEEE80211_RADIOTAP_HE_DATA1_STBC_KNOWN = 0x0200, IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE_KNOWN = 0x0400, IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE2_KNOWN = 0x0800, IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE3_KNOWN = 0x1000, IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE4_KNOWN = 0x2000, IEEE80211_RADIOTAP_HE_DATA1_BW_RU_ALLOC_KNOWN = 0x4000, IEEE80211_RADIOTAP_HE_DATA1_DOPPLER_KNOWN = 0x8000, IEEE80211_RADIOTAP_HE_DATA2_PRISEC_80_KNOWN = 0x0001, IEEE80211_RADIOTAP_HE_DATA2_GI_KNOWN = 0x0002, IEEE80211_RADIOTAP_HE_DATA2_NUM_LTF_SYMS_KNOWN = 0x0004, IEEE80211_RADIOTAP_HE_DATA2_PRE_FEC_PAD_KNOWN = 0x0008, IEEE80211_RADIOTAP_HE_DATA2_TXBF_KNOWN = 0x0010, IEEE80211_RADIOTAP_HE_DATA2_PE_DISAMBIG_KNOWN = 0x0020, IEEE80211_RADIOTAP_HE_DATA2_TXOP_KNOWN = 0x0040, IEEE80211_RADIOTAP_HE_DATA2_MIDAMBLE_KNOWN = 0x0080, IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET = 0x3f00, IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET_KNOWN = 0x4000, IEEE80211_RADIOTAP_HE_DATA2_PRISEC_80_SEC = 0x8000, IEEE80211_RADIOTAP_HE_DATA3_BSS_COLOR = 0x003f, IEEE80211_RADIOTAP_HE_DATA3_BEAM_CHANGE = 0x0040, IEEE80211_RADIOTAP_HE_DATA3_UL_DL = 0x0080, IEEE80211_RADIOTAP_HE_DATA3_DATA_MCS = 0x0f00, IEEE80211_RADIOTAP_HE_DATA3_DATA_DCM = 0x1000, IEEE80211_RADIOTAP_HE_DATA3_CODING = 0x2000, IEEE80211_RADIOTAP_HE_DATA3_LDPC_XSYMSEG = 0x4000, IEEE80211_RADIOTAP_HE_DATA3_STBC = 0x8000, IEEE80211_RADIOTAP_HE_DATA4_SU_MU_SPTL_REUSE = 0x000f, IEEE80211_RADIOTAP_HE_DATA4_MU_STA_ID = 0x7ff0, IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE1 = 0x000f, IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE2 = 0x00f0, IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE3 = 0x0f00, IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE4 = 0xf000, IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC = 0x000f, IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_20MHZ = 0, IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_40MHZ = 1, IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_80MHZ = 2, IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_160MHZ = 3, IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_26T = 4, IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_52T = 5, IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_106T = 6, IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_242T = 7, IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_484T = 8, IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_996T = 9, IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_2x996T = 10, IEEE80211_RADIOTAP_HE_DATA5_GI = 0x0030, IEEE80211_RADIOTAP_HE_DATA5_GI_0_8 = 0, IEEE80211_RADIOTAP_HE_DATA5_GI_1_6 = 1, IEEE80211_RADIOTAP_HE_DATA5_GI_3_2 = 2, IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE = 0x00c0, IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_UNKNOWN = 0, IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_1X = 1, IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_2X = 2, IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_4X = 3, IEEE80211_RADIOTAP_HE_DATA5_NUM_LTF_SYMS = 0x0700, IEEE80211_RADIOTAP_HE_DATA5_PRE_FEC_PAD = 0x3000, IEEE80211_RADIOTAP_HE_DATA5_TXBF = 0x4000, IEEE80211_RADIOTAP_HE_DATA5_PE_DISAMBIG = 0x8000, IEEE80211_RADIOTAP_HE_DATA6_NSTS = 0x000f, IEEE80211_RADIOTAP_HE_DATA6_DOPPLER = 0x0010, IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW_KNOWN = 0x0020, IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW = 0x00c0, IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW_20MHZ = 0, IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW_40MHZ = 1, IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW_80MHZ = 2, IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW_160MHZ = 3, IEEE80211_RADIOTAP_HE_DATA6_TXOP = 0x7f00, IEEE80211_RADIOTAP_HE_DATA6_MIDAMBLE_PDCTY = 0x8000, }; struct ieee80211_radiotap_he_mu { uint16_t flags1, flags2; uint8_t ru_ch1[4]; uint8_t ru_ch2[4]; }; enum ieee80211_radiotap_he_mu_bits { IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_MCS = 0x000f, IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_MCS_KNOWN = 0x0010, IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_DCM = 0x0020, IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_DCM_KNOWN = 0x0040, IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH2_CTR_26T_RU_KNOWN = 0x0080, IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH1_RU_KNOWN = 0x0100, IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH2_RU_KNOWN = 0x0200, IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH1_CTR_26T_RU_KNOWN = 0x1000, IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH1_CTR_26T_RU = 0x2000, IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_COMP_KNOWN = 0x4000, IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_SYMS_USERS_KNOWN = 0x8000, IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW = 0x0003, IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_20MHZ = 0x0000, IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_40MHZ = 0x0001, IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_80MHZ = 0x0002, IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_160MHZ = 0x0003, IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_KNOWN = 0x0004, IEEE80211_RADIOTAP_HE_MU_FLAGS2_SIG_B_COMP = 0x0008, IEEE80211_RADIOTAP_HE_MU_FLAGS2_SIG_B_SYMS_USERS = 0x00f0, IEEE80211_RADIOTAP_HE_MU_FLAGS2_PUNC_FROM_SIG_A_BW = 0x0300, IEEE80211_RADIOTAP_HE_MU_FLAGS2_PUNC_FROM_SIG_A_BW_KNOWN= 0x0400, IEEE80211_RADIOTAP_HE_MU_FLAGS2_CH2_CTR_26T_RU = 0x0800, }; enum ieee80211_radiotap_lsig_data1 { IEEE80211_RADIOTAP_LSIG_DATA1_RATE_KNOWN = 0x0001, IEEE80211_RADIOTAP_LSIG_DATA1_LENGTH_KNOWN = 0x0002, }; enum ieee80211_radiotap_lsig_data2 { IEEE80211_RADIOTAP_LSIG_DATA2_RATE = 0x000f, IEEE80211_RADIOTAP_LSIG_DATA2_LENGTH = 0xfff0, }; struct ieee80211_radiotap_lsig { uint16_t data1, data2; }; enum ieee80211_radiotap_zero_len_psdu_type { IEEE80211_RADIOTAP_ZERO_LEN_PSDU_SOUNDING = 0, IEEE80211_RADIOTAP_ZERO_LEN_PSDU_NOT_CAPTURED = 1, IEEE80211_RADIOTAP_ZERO_LEN_PSDU_VENDOR = 0xff, }; /** * ieee80211_get_radiotap_len - get radiotap header length */ static inline uint16_t ieee80211_get_radiotap_len(const char *data) { struct ieee80211_radiotap_header *hdr = (void *)data; return get_unaligned_le16(&hdr->it_len); } #endif /* __RADIOTAP_H */ |
ここからが、本体のcソースになります。
まずは、ライブラリのインクルードと各種定義をします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
#include<sys/types.h> #include<sys/ioctl.h> #include<stdio.h> #include<string.h> #include<stdlib.h> #include<unistd.h> #include<netinet/in.h> #include<net/if.h> #include<linux/if_packet.h> #include<linux/if_ether.h> #include "ieee80211_radiotap.h" #include "ieee80211.h" #define IEEE80211_ADDR_LEN 6 #define IEEE80211_RATE_BASIC 0x01 #define IEEE80211_RATE_VAL 0x0e #define BEACON_INTERVAL 102400 struct ieee80211_beacon{ uint64_t beacon_timestamp; uint16_t beacon_interval; uint16_t beacon_capabilities; }__attribute__((__packed__)); struct ieee80211_info_element{ uint8_t info_elemid; uint8_t info_length; uint8_t *info[0]; }__attribute__((__packed__)); struct AccessPointDescriptor { uint8_t macAddress[IEEE80211_ADDR_LEN]; const uint8_t *ssid; size_t ssidLength; const uint8_t *dataRates; size_t dataRatesLength; }; static const uint8_t IEEE80211_BROADCAST_ADDR[IEEE80211_ADDR_LEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; static const uint8_t IEEE80211B_DEFAULT_RATES[] = { IEEE80211_RATE_BASIC | 2, IEEE80211_RATE_BASIC | 4, 11, 22 }; #define IEEE80211B_DEFAULT_RATES_LENGTH sizeof(IEEE80211B_DEFAULT_RATES) static struct AccessPointDescriptor ap = { {0x08, 0x00, 0x27, 0xa1, 0x58, 0x8d}, (const uint8_t *)"Hello World!", 12, IEEE80211B_DEFAULT_RATES, IEEE80211B_DEFAULT_RATES_LENGTH, }; |
IEEE80211_RATE_BASICは、サポートレートを指定したときに、必須レートにする値とビット和をとるためのものです。こうすることで、データレートの必須フラグを立てます。
Beacon_Intervalは102400を指定します。実際のビーコンフレームに入れるときは、タイムユニットという単位(1,024μ秒)です。代入時にBeacon_Intervalを1,024で割ってあげることで、100タイムユニット(約0.1秒)をセットすることが出来ます。
あとは、ビーコンフレームのペイロード部分を、固定フィールドと情報エレメントに分けて定義します。APの情報に関してもここで、定義しておきます。
次は、ソケットを作成する関数です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
int opensocket(const char device[IFNAMSIZ]) { struct ifreq ifr; struct sockaddr_ll sll; const int protocol = ETH_P_ALL; int soc = -1; soc = socket(PF_PACKET, SOCK_RAW, htons(protocol)); if(soc<0){ perror("[-]socket failed"); return -1; } memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); if(ioctl(soc, SIOCGIFINDEX, &ifr)<0){ perror("[-]ioctl[SIOCGIFINDEX]"); close(soc); return -1; } memset(&sll, 0, sizeof(sll)); sll.sll_family = AF_PACKET; sll.sll_protocol = htons(protocol); sll.sll_ifindex = ifr.ifr_ifindex; if(bind(soc, (struct sockaddr *)&sll, sizeof(sll))<0){ perror("[-]bind[AF_PACKET]"); close(soc); return -1; } return soc; } |
ビーコンフレームを実際に作成するための関数です。radiotap、MACヘッダーなどのフィールドを順番にセットしていきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
uint8_t *constructBeaconPacket(uint8_t dataRate, uint8_t channel, size_t beaconLength) { uint8_t dataRateValue = (dataRate & IEEE80211_RATE_VAL); uint8_t *packet = (uint8_t*)malloc(beaconLength); if(packet == NULL){ return NULL; } struct ieee80211_radiotap_header *radiotap = (struct ieee80211_radiotap_header *)packet; uint8_t *packetIterator = packet + sizeof(*radiotap); radiotap->it_version = 0; radiotap->it_len = sizeof(*radiotap) + sizeof(dataRate); radiotap->it_present = (1 << IEEE80211_RADIOTAP_RATE); *packetIterator = (dataRate & IEEE80211_RATE_VAL); packetIterator ++; struct ieee80211_frame *mac_header = (struct ieee80211_frame*)packetIterator; packetIterator += sizeof(*mac_header); mac_header->i_fc = 0; mac_header->i_fc = IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON; mac_header->i_dur = 0; memcpy(mac_header->i_addr1, IEEE80211_BROADCAST_ADDR, IEEE80211_ADDR_LEN); memcpy(mac_header->i_addr2, ap.macAddress, IEEE80211_ADDR_LEN); memcpy(mac_header->i_addr3, ap.macAddress, IEEE80211_ADDR_LEN); struct ieee80211_beacon *beacon = (struct ieee80211_beacon *)packetIterator; packetIterator += sizeof(*beacon); beacon->beacon_timestamp = 0; beacon->beacon_interval = htole16(BEACON_INTERVAL/1024); beacon->beacon_capabilities = htole16(0x0001); struct ieee80211_info_element *info = (struct ieee80211_info_element *)packetIterator; packetIterator += sizeof(struct ieee80211_info_element) + ap.ssidLength; info->info_elemid = IEEE80211_ELEMID_SSID; info->info_length = ap.ssidLength; memcpy(info->info, ap.ssid, ap.ssidLength); info = (struct ieee80211_info_element *)packetIterator; packetIterator += sizeof(struct ieee80211_info_element) + ap.dataRatesLength; info->info_elemid = IEEE80211_ELEMID_RATES; info->info_length = ap.dataRatesLength; memcpy(info->info, ap.dataRates, ap.dataRatesLength); info = (struct ieee80211_info_element *)packetIterator; packetIterator += sizeof(struct ieee80211_info_element) + sizeof(channel); info->info_elemid = IEEE80211_ELEMID_DSPARAMS; info->info_length = sizeof(channel); memcpy(info->info, &channel, sizeof(channel)); return packet; } |
main関数です。
実行時に、インタフェース名とチャネル番号を一緒に指定します。まずは、ソケットを開いて、ビーコンフレームを組み立てて、送信するといった、シンプルな流れです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
int main(int argc, char *argv[]) { if(argc != 3){ printf("[-]Fake AP [deveice] [channel]\n"); return -1; } uint64_t channel = strtol(argv[2], NULL, 10); if(channel <= 0 || 255 <= channel){ printf("[-]The channel must be between 1 and 255.\n"); return -1; } const char *device = argv[1]; int soc = opensocket(device); if(soc<0){ fprintf(stderr, "[-]Error opening socket: %s\n", device); return -1; } printf("[+]Socket was created\n"); const uint8_t dataRate = 0x4; size_t beaconLength = sizeof(struct ieee80211_radiotap_header) + sizeof(dataRate) + sizeof(struct ieee80211_frame) + sizeof(struct ieee80211_beacon) + sizeof(struct ieee80211_info_element)*3 + ap.ssidLength + ap.dataRatesLength + sizeof(channel); uint8_t *beaconPacket = (uint8_t *)malloc(sizeof(beaconLength)); printf("[+]Beacon Length: %d\n", beaconLength); beaconPacket = constructBeaconPacket(dataRate, channel, beaconLength); printf("[+]Created Beacon Frame: %d\n"); while(1) { ssize_t bytes = write(soc, beaconPacket, beaconLength); if(bytes < (ssize_t)beaconLength){ perror("[-]Error sending packet"); return -1; } printf("[+]Beacon was sent\n"); } close(soc); free(beaconPacket); } |
実行するときの注意ですが、無線LANアダプターを別に用意する必要があります。PC内蔵の無線LANアダプターでは機能が限られているので、外付け無線LANアダプターでないと動作しません。内蔵の無線LANアダプターは、Managedモードというモードで動作しています。
しかし今回のようにAPとして動作させるには、無線LANアダプターをMonitorモードにしてあげる必要があります。また外付けの無線LANアダプターなら、どれでもよいというわけではありません。ここは少し難しい話になってしまいますが、無線LANアダプターの中にあるチップセットというものが関係してきます。
どれを買っらたよいか分からない、という方もいると思いますので、私も参考になったサイトを載せておきますね。
- https://miloserdov.org/?p=2196
- https://null-byte.wonderhowto.com/how-to/buy-best-wireless-network-adapter-for-wi-fi-hacking-2019-0178550/
それでは実際に実行してみます。
偽のAPをスマホに認識させる
まずは、モニターモードにします。
外付け無線LANアダプターをPCに、単に接続しただけでの状態で、iwconfigで確認してみます。Managedモードになっています。いわば、通常のモードです。

以下のコマンドを叩いて、monitorモードに切り替えます。
- ifconfig wlan0 down
- iwconfig wlan0 mode monitor
- ifconfig wlan0 up
再度、iwconfigで確認してみると、Monitorモードになっているのが分かります。これで下準備は完了です。あとはこのインタフェースに、ビーコンフレームを送信するのみです。

実行するとこのようになります。

それでは、スマホの方で確認してみます。

Hello Worldと名付けたSSIDで、APの存在が確認できました!
最後まで読んでいただきありがとうございました。