├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ └── cpush.yml ├── .gitignore ├── Makefile ├── README.md ├── changelog ├── docs ├── config.txt ├── example-pic-1.png ├── example-pic-2.png ├── example-pic-3.png ├── example.md ├── gpiowait.png ├── hardware-mod.md ├── lessons_learned.txt └── option-codes.md ├── hcxdumptool.c ├── hcxnmealog.c ├── include ├── byteorder.h ├── hcxdumptool.h ├── hcxlabtool.h ├── hcxnmealog.h ├── ieee80211.h ├── pcapng.h ├── radiotap.h ├── raspberry.h └── types.h ├── license.txt ├── man └── hcxdumptool.1 └── usefulscripts ├── startnlmon ├── startnm └── stopnm /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Please report bugs here 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **GitHub is for bugs and features - not for support** 11 | Questions must be posted in the discussion board https://github.com/ZerBea/hcxdumptool/discussions 12 | 13 | **Check the FAQ** 14 | Please review the discussions 15 | 16 | **Comment output of** 17 | 1. $ sudo hcxdumptool -v 18 | 2. $ sudo hcxdumptool -l 19 | Bug reports will only be accepted against the current tip of the master git branch. Anything else will be rejected. 20 | 21 | **Describe the bug** 22 | A clear and concise description of what the bug is. 23 | 24 | **To Reproduce** 25 | Comment the entire command line 26 | 27 | **Expected behavior** 28 | A clear and concise description of what you expected to happen. 29 | 30 | **Screenshots** 31 | If applicable, add screenshots to help explain your problem. 32 | 33 | **Additional context** 34 | Add any other context about the problem here. 35 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **GitHub is for bugs and features - not for support** 11 | Questions must be posted in the discussion board https://github.com/ZerBea/hcxdumptool/discussions 12 | 13 | **Check the FAQ** 14 | Some items that might appear to be issues are not issues. Please review the discussions. 15 | 16 | **Describe the feature** 17 | A clear and concise description of what the feature is. 18 | 19 | **Current behavior** 20 | Please give a reproducible example of the current behavior, if possible. 21 | 22 | **Expected behavior** 23 | A clear and concise description of what you expected to happen, ideally with mock output. 24 | 25 | **Additional context** 26 | Add any other context or screenshots about the feature request here. 27 | -------------------------------------------------------------------------------- /.github/workflows/cpush.yml: -------------------------------------------------------------------------------- 1 | name: C CI 2 | 3 | on: 4 | push: 5 | branches: [ "master" ] 6 | pull_request: 7 | branches: [ "master" ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ubuntu-latest 13 | 14 | strategy: 15 | matrix: 16 | os-version: [ ubuntu-latest ] 17 | compiler: [ gcc-latest ] 18 | deps: ['enabled'] 19 | platform: ['x64', 'x86'] 20 | 21 | steps: 22 | - uses: actions/checkout@v3 23 | with: 24 | fetch-depth: 0 25 | 26 | - name: Install packages 27 | run: | 28 | sudo apt update 29 | sudo apt install -y libpcap-dev 30 | 31 | - name: Make 32 | run: make 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | hcxdumptool 2 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PRODUCTION := 0 2 | PRODUCTION_VERSION := 6.3.5 3 | PRODUCTION_YEAR := 2025 4 | 5 | ifeq ($(PRODUCTION),1) 6 | VERSION_TAG := $(PRODUCTION_VERSION) 7 | else 8 | VERSION_TAG := $(shell git describe --tags || echo $(PRODUCTION_VERSION)) 9 | endif 10 | VERSION_YEAR := $(shell echo $(PRODUCTION_YEAR)) 11 | 12 | PREFIX ?= /usr 13 | BINDIR = $(DESTDIR)$(PREFIX)/bin 14 | 15 | HOSTOS := $(shell uname -s) 16 | 17 | CC ?= gcc 18 | CFLAGS ?= -O3 -Wall -Wextra -Wpedantic 19 | CFLAGS += -std=gnu99 20 | # uncomment to enable DEBUG symbols 21 | #CFLAGS += -ggdb -fsanitize=address 22 | DEFS = -DVERSION_TAG=\"$(VERSION_TAG)\" -DVERSION_YEAR=\"$(VERSION_YEAR)\" 23 | # comment to disable STATUS display (headless operation) 24 | DEFS += -DHCXSTATUSOUT 25 | # comment to disable BPF compiler 26 | DEFS += -DHCXWANTLIBPCAP 27 | LDFLAGS += -lpcap 28 | # uncomment to enable DEBUG log 29 | #DEFS += -DHCXDEBUG 30 | 31 | INSTALL ?= install 32 | INSTFLAGS = 33 | 34 | ifeq ($(HOSTOS), Linux) 35 | INSTFLAGS += -D 36 | endif 37 | 38 | TOOLS=hcxdumptool 39 | TOOLS+=hcxnmealog 40 | 41 | .PHONY: all build install clean uninstall 42 | 43 | all: build 44 | 45 | build: $(TOOLS) 46 | 47 | # $1: tool name 48 | define tool-build 49 | $(1)_src ?= $(1).c 50 | $(1)_libs ?= 51 | $(1)_cflags ?= 52 | 53 | $(1): $$($(1)_src) 54 | $$(CC) $$(CFLAGS) $$($(1)_cflags) $$(CPPFLAGS) -o $$@ $$($(1)_src) $$(DEFS) $$(LDFLAGS) 55 | 56 | .deps/$(1).d: $(1) 57 | 58 | .PHONY: $(1).install 59 | $(1).install: $(1) 60 | $$(INSTALL) $$(INSTFLAGS) -m 0755 $(1) $$(BINDIR)/$(1) 61 | 62 | .PHONY: $(1).clean 63 | $(1).clean: 64 | rm -f .deps/$(1).d 65 | rm -f $(1) 66 | 67 | .PHONY: $(1).uninstall 68 | $(1).uninstall: 69 | rm -rf $$(BINDIR)/$(1) 70 | 71 | endef 72 | 73 | $(foreach tool,$(TOOLS),$(eval $(call tool-build,$(tool)))) 74 | 75 | install: $(patsubst %,%.install,$(TOOLS)) 76 | 77 | clean: $(patsubst %,%.clean,$(TOOLS)) 78 | rm -rf .deps 79 | rm -f *.o *~ 80 | 81 | uninstall: $(patsubst %,%.uninstall,$(TOOLS)) 82 | 83 | -include .deps/*.d 84 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # hcxdumptool 2 | 3 | A tool to capture packets from WLAN devices and to discover potential weak points within own WiFi networks by running layer 2 attacks against the WPA protocol. 4 | 5 | Designed to to run (mostly headless) on small systems like a Raspberry Pi Zero. 6 | 7 | # hcxnmealog 8 | 9 | A tool to handle NMEA 0183 sentences from GPS devices. 10 | 11 | Designed to to run (mostly headless) on small systems like a Raspberry Pi Zero. 12 | 13 | ### General Information 14 | 15 | - [An overview of Hashcat mode 22000.](https://hashcat.net/wiki/doku.php?id=cracking_wpawpa2) 16 | 17 | - [A set of tools by **ZerBea** intended for processing capture files.](https://github.com/ZerBea/hcxtools) 18 | 19 | - [Old but still applicable write-up by **atom** of the Hashcat forums covering a new attack on WPA/WPA2 using PMKID.](https://hashcat.net/forum/thread-7717.html) 20 | 21 | - [Hashcat mode 22000 write-up by **atom** of the Hashcat forums.](https://hashcat.net/forum/thread-10253.html) 22 | 23 | - [A write-up by **Ido Hoorvitch** from CyberArk covering the statistics of WPA/WPA2 password cracking.](https://www.cyberark.com/resources/threat-research-blog/cracking-wifi-at-scale-with-one-simple-trick) 24 | 25 | - [A section of this README that covers hcxdumptool's abilities and the responsibilities of using it.](https://github.com/ZerBea/hcxdumptool#caution) 26 | 27 | - hcxdumptool uses the modern [pcapng](https://pcapng.com/) format, allowing for use with wireshark or tshark. 28 | 29 | - [A document showcasing an example attack using hcxdumptool and hcxtools.](https://github.com/ZerBea/hcxdumptool/blob/master/docs/example.md) 30 | 31 | ### What Doesn't hcxdumptool Do? 32 | 33 | - It does not crack WPA PSK related hashes. (Use Hashcat or JtR to recover the PSK.) 34 | 35 | - It does not crack WEP. (Use the aircrack-ng suite instead.) 36 | 37 | - It does not crack WPS. (Use Reaver or Bully instead.) 38 | 39 | - It does not decrypt encrypted traffic. (Use tshark or Wireshark in parallel.) 40 | 41 | - It does not record all traffic captured on the WLAN device. (Use tshark or Wireshark in parallel.) 42 | 43 | - It does not perform Evil Twin attacks. 44 | 45 | - It does not provide a beautiful status display. 46 | 47 | - It is not a honey pot. 48 | 49 | **Unsupported:** Windows OS, macOS, Android, emulators or wrappers! 50 | 51 | > [!NOTE] 52 | > 53 | > **hcxdumptool** does not perform conversion or cracking! It is designed to be used in conjunction with the following tools: 54 | > 55 | > | Tool | Description | 56 | > | ------------- | ------------------------------------------------------------------------------------------------------| 57 | > | hcxnmealog | Tool to handle NMEA 0183 sentences | 58 | > | hcxpcapngtool | Tool to convert raw PCAPNG files to Hashcat and JtR readable formats. (hcxtools) | 59 | > | hcxhashtool | Tool to filter hashes from HC22000 files based on user input. (hcxtools) | 60 | > | hcxpsktool | Tool to get weak PSK candidates from HC22000 files. (hcxtools) | 61 | > | hcxeiutool | Tool to calculate wordlists based off ESSIDs gathered. (hcxtools) | 62 | > | Hashcat/JtR | Third party tools used to infer PSK from HC22000 hash files. | 63 | > 64 | > **hcxtools** can be found [here](https://github.com/ZerBea/hcxtools). Hashcat can be found [here](https://github.com/hashcat/hashcat). 65 | 66 | ### Work Flow 67 | 68 | hcxdumptool -> hcxpcapngtool -> hcxhashtool (additional hcxpsktool/hcxeiutool) -> Hashcat or JtR 69 | 70 | ### Requirements 71 | 72 | You might expect me to recommend that everyone should be using hcxdumptool/hcxtools. But the fact of the matter is, however, that hcxdumptool/hcxtools is NOT recommended to be used by unexperienced users or newbies. 73 | If you are not familiar with Linux generally or if you do not have at least a basic level of knowledge as mentioned in section "Requirements", hcxdumptool/hcxtools is probably not what you are looking for. 74 | However, if you have that knowledge this tools can do magic. 75 | 76 | - Knowledge of radio technology. 77 | - Knowledge of electromagnetic-wave engineering. 78 | - Detailed knowledge of 802.11 protocol. 79 | - Detailed knowledge of key derivation functions. 80 | - Detailed knwoldege of NMEA 0183 protocol. 81 | - Detailed knowledge of Linux. 82 | - Detailed knowledge of filter procedures. (Berkeley Packet Filter, capture filter, display filter, etc.) 83 | - Detailed knowledge of Bolean Operators. 84 | - Operating system: Linux (latest longterm or stable [kernel](https://www.kernel.org), mandatory >= 5.15) 85 | - Recommended distribution: [Arch Linux](https://archlinux.org/) (notebooks and desktop systems), [OpenWRT](https://openwrt.org/) (small systems like Raspberry Pi, WiFi router) 86 | - WLAN device chipset must be able to run in monitor mode. 87 | - WLAN device driver *must* support monitor and full frame injection mode. 88 | - gcc >= 14 recommended (deprecated versions are not supported: https://gcc.gnu.org/) 89 | - make 90 | - libpcap and libpcap-dev (If internal BPF compiler has been enabled.) 91 | - Raspberry Pi A, B, A+, B+, Zero (WH). (Recommended: Zero or A+, because of a very low power consumption), but notebooks and desktops will work as well. 92 | - GPIO hardware mod recommended (push button and LED) on Raspberry Pi 93 | - To allow 5/6/7GHz packet injection, it is mandatory to uncomment a regulatory domain that support this: /etc/conf.d/wireless-regdom 94 | - Make sure that the version of hcxdumptool always fits to the version of hcxpcapngtool 95 | 96 | ### Install Guide 97 | 98 | > [!IMPORTANT] 99 | > 100 | > While hcxdumptool and hcxtools are available through the package manager on most distributions, these packages are usually very old and outdated, thus cloning and building is recommended. 101 | > 102 | > Make sure that your distribution is updated to it's latest version and make sure that all header files and dependencies have been installed BEFORE attempting to compile! 103 | > 104 | > The packages mentioned in the "Requirements" section sometimes come under different names in a package manager! Make sure to install the correct packages! 105 | 106 | #### Clone Repository 107 | 108 | ``` 109 | git clone https://github.com/ZerBea/hcxdumptool.git 110 | cd hcxdumptool 111 | ``` 112 | 113 | #### Compile & Install 114 | 115 | Compiling: 116 | ``` 117 | make -j $(nproc) 118 | ``` 119 | 120 | Installing to `/usr/bin`: 121 | ``` 122 | make install (as super user) 123 | ``` 124 | 125 | Or installing to `/usr/local/bin`: 126 | ``` 127 | make install PREFIX=/usr/local (as super user) 128 | ``` 129 | 130 | > [!TIP] 131 | > 132 | > On headless operation, remove -DSTATUSOUT from the Makefile before compiling! That way, the status display will not be compiled. This will save CPU cycles and prevent ERRORs from occurring. 133 | > 134 | > It is theoretically possible to compile hcxdumptool for other systems (e.g. Android) and other distributions (e.g. KALI) and other operating systems (BSD) as well. 135 | > There is no plan to support the operating systems and feature requests will be rejected. 136 | 137 | ### Adapters 138 | 139 | > [!WARNING] 140 | > 141 | > - Do not expect flawless drivers on brand new hardware! 142 | > 143 | > - Driver must support monitor mode and full packet injection! 144 | > 145 | > - PRISM devices are _not_ supported! 146 | > 147 | > - WIRELESS EXTENSIONS are deprecated and no longer supported! 148 | 149 | > [!NOTE] 150 | > 151 | > Manufacturers do change chipsets without changing model numbers. Sometimes they add (v)ersion or (rev)vision. 152 | > As long as a manufacturer or a company does not consider it necessary to supply drivers to the Linux kernel avoid to buy this products! 153 | > 154 | > **Always verify the actual chipset with 'lsusb' and/or 'lspci'!** 155 | > 156 | > No support for a third party driver which is not part of the [official Linux kernel](https://www.kernel.org/). 157 | > Report related issues to the site, from which you downloaded the driver. 158 | > 159 | > No support for a driver which doesn't support monitor mode and full frame injection natively. 160 | > If you need these features, do a request on www.kernel.org 161 | > 162 | > Several device and driver tests can be found [here](https://github.com/ZerBea/hcxdumptool/discussions/361). 163 | > Dependent on the version of the Linux kernel, expect massive driver issues. 164 | 165 | Known as working WiFi chipsets: 166 | 167 | * Atheros (ath9k_htc) old chipset 168 | 169 | * Ralink (rt2800usb) old chipset 170 | 171 | * MediaTek (mt76) depending on chipset and the version of the Linux Kernel expect massive driver issues 172 | 173 | * Realtek (rtl8xxxu) depending on chpset and the version of the Linux Kernel expect massive driver issues 174 | 175 | Not recommended WiFi chipsets: 176 | 177 | * Intel (Monitor mode and frame injection problems.) 178 | 179 | * Broadcom (Neither monitor mode nor frame injection by official Linux kernel.) 180 | 181 | * Qualcomm (No frame injection by official Linux kernel.) 182 | 183 | Absolutely not recommended: 184 | 185 | * All kinds of WiFi PCIe cards, due to massive interference. 186 | https://duckduckgo.com/?t=ffab&q=Static+Interference+from+PCIe+wifi&ia=web 187 | 188 | More information about possible issues or limitations can be found [here](https://github.com/ZerBea/hcxdumptool#useful-links). 189 | 190 | ### Antennas 191 | 192 | The best high frequency amplifier is a good antenna! 193 | 194 | It is much better to achieve gain using a good antenna instead of increasing transmission power. 195 | 196 | | VENDOR MODEL | TYPE | 197 | | ---------------------- | --------------- | 198 | | LOGILINK WL0097 | Grid Parabolic | 199 | | TP-LINK TL-ANT2414 A/B | Panel | 200 | | LevelOne WAN-1112 | Panel | 201 | | DELOCK 88806 | Panel | 202 | | TP-LINK TL-ANT2409 A | Panel | 203 | 204 | ### GPS devices (NMEA 0183 protocol) 205 | 206 | | VENDOR MODEL | TYPE | 207 | | --------------------------- | --------------- | 208 | | NAVILOCK NL-701US | USB | 209 | | JENTRO BT-GPS-8 activepilot | BLUETOOTH | 210 | | HiLetgo VK172 | USB | 211 | 212 | ### Useful Scripts 213 | 214 | | Script | Description | 215 | | ------------ | -------------------------------------------------------- | 216 | | stopnm | Example script to stop NetworkManager | 217 | | startnm | Example script to start NetworkManager | 218 | | startnlmon | Example script to activate NETLINK monitor | 219 | 220 | ### Caution! 221 | 222 | You might expect me to recommend that everyone should be using hcxdumptool/hcxtools. But the fact of the matter is, hcxdumptool/hcxtools is _NOT_ recommended to be used by inexperienced users or newbies. 223 | 224 | If you are not familiar with Linux in general or you do not have at least a basic level of knowledge as mentioned in the "Requirements" section, hcxdumptool/hcxtools is probably not what you are looking for. 225 | However, if you have that knowledge hcxdumptool/hcxtools can do magic for you. 226 | 227 | Misuse of hcxdumptool within a network, particularly without authorization, may cause irreparable damage and result in significant consequences. “Not understanding what you were doing” is not going to work as an excuse. 228 | 229 | The entire toolkit (hcxdumptool and hcxtools) is designed to be an analysis toolkit. 230 | 231 | **hcxdumptool should only be used in a 100% controlled environment!** 232 | 233 | If you can't control the environment, it is absolutely mandatory to set the [BPF](https://wiki.wireshark.org/CaptureFilters)! 234 | 235 | The BPF can be used to select a target (or multible targets) or to protect devices. 236 | 237 | By default, hcxdumptool is utilizing three attack vectors: 238 | 239 | - Connecting to an ACCESS POINT to get a PMKID (turn off by --attemptapmax) 240 | 241 | - Disconnecting a CLIENT from an associated ACCESS POINT to get a complete handshake (M1M2M3M4) and a PMKID (turn off by --attemptapmax) 242 | 243 | - Allowing a CLIENT to connect to hcxdumptool to get a challenge (M1M2) or an EAP-ID (turn off by --attemptclientmax) 244 | 245 | > [!WARNING] 246 | > 247 | > **You may only use hcxdumptool on networks that you have permission to attack, because:** 248 | > 249 | > - hcxdumptool is able to prevent complete WLAN traffic transmission. (Depending on selected options.) 250 | > 251 | > - hcxdumptool is able to capture PMKIDs from access points if the accesspoint supports PMKID caching. (Only one single PMKID from an access point is required. Use hcxpcapngtool to convert them to a format Hashcat or JtR understands.) 252 | > 253 | > - hcxdumptool is able to capture handshakes from non-connected clients. (Only one single M2 from the client is required. Use hcxpcapngtool to convert them to a format Hashcat or JtR understands.) 254 | > 255 | > - hcxdumptool is able to capture handshakes from 5/6GHz clients on 2.4GHz. (Only one single M2 from the client is required. Use hcxpcapngtool to convert to a format Hashcat or JtR understands.) 256 | > 257 | > - hcxdumptool is able to capture passwords from the WLAN traffic. (Use hcxpcapngtool -R to save them to file, or together with networknames [-E].) 258 | > 259 | > - hcxdumptool is able to request and capture extended EAPOL. (RADIUS, GSM-SIM, WPS. hcxpcapngtool will show you information about them.) 260 | > 261 | > - hcxdumptool is able to capture identities from the WLAN traffic. (Example: Request IMSI numbers from mobile phones - use hcxpcapngtool -I to save them to file.) 262 | > 263 | > - hcxdumptool is able to capture usernames from the WLAN traffic. (Example: User name of a server authentication - use hcxpcapngtool -U to save them to file.) 264 | > 265 | > **Do Not:** 266 | > 267 | > - Use a logical interface and leave the physical interface in managed mode! 268 | > 269 | > - Use hcxdumptool in combination with the aircrack-ng suite, Reaver, Bully, or any other tools that take access to the interface! 270 | > 271 | > - Use tools like macchanger as they are useless since hcxdumptool uses its own random MAC address space. 272 | > 273 | > - Merge PCAPNG dumpfiles because doing so will destroy custom block hash assignments! 274 | 275 | ### Useful Links 276 | 277 | - [PCAPNG Format Information](https://pcapng.com/) 278 | 279 | - [The Linux Kernel Documentation](https://www.kernel.org/doc/html/latest/) 280 | 281 | - [Existing Linux Wireless drivers](https://wireless.docs.kernel.org/en/latest/en/users/drivers.html) 282 | 283 | - [BPF Documentation](https://www.kernel.org/doc/html/latest/bpf/index.html) 284 | 285 | - [Linux Commands Handbook](https://www.freecodecamp.org/news/the-linux-commands-handbook/) 286 | 287 | - [WPA2 Information](https://en.wikipedia.org/wiki/Wpa2) 288 | 289 | - [802.11 Frame Types](https://en.wikipedia.org/wiki/802.11_Frame_Types) 290 | 291 | - [802.11 Security Improvements](https://en.wikipedia.org/wiki/IEEE_802.11i-2004) 292 | 293 | - [Kernel Bugzilla](https://bugzilla.kernel.org) 294 | 295 | - [About ath10k](https://wireless.wiki.kernel.org/en/users/Drivers/ath10k) 296 | 297 | - [Status of Realtek out-of-kernel Drivers](https://github.com/morrownr/USB-WiFi/issues/314) 298 | 299 | - [PCAPNG Status Options](https://github.com/ZerBea/hcxdumptool/blob/master/docs/option-codes.md) 300 | -------------------------------------------------------------------------------- /docs/config.txt: -------------------------------------------------------------------------------- 1 | # See /boot/overlays/README for all available options 2 | 3 | gpu_mem=64 4 | initramfs initramfs-linux.img followkernel 5 | max_usb_current=1 6 | hdmi_blanking=1 7 | dtoverlay=pi3-disable-bt 8 | dtoverlay=pi3-disable-wifi 9 | dtparam=audio=off 10 | dtparam=watchdog=on 11 | disable_splash=1 12 | tparam=pwr_led_trigger=none 13 | dtparam=pwr_led_activelow=off 14 | dtparam=act_led_trigger=none 15 | dtparam=act_led_activelow=on 16 | -------------------------------------------------------------------------------- /docs/example-pic-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZerBea/hcxdumptool/dabec8ac0c31b0a64d6f2387e6a420debf873258/docs/example-pic-1.png -------------------------------------------------------------------------------- /docs/example-pic-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZerBea/hcxdumptool/dabec8ac0c31b0a64d6f2387e6a420debf873258/docs/example-pic-2.png -------------------------------------------------------------------------------- /docs/example-pic-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZerBea/hcxdumptool/dabec8ac0c31b0a64d6f2387e6a420debf873258/docs/example-pic-3.png -------------------------------------------------------------------------------- /docs/example.md: -------------------------------------------------------------------------------- 1 | # Example Attack - Overview 2 | 3 | > [!NOTE] 4 | > This guide is only a general outline for attacks. 5 | > This guide is not definitive as there is no "one size fits all" solution for attacking networks. 6 | > This is the reason for the many options that hcxdumptool/hcxtools offers. 7 | > More information: 8 | > - [An overview of Hashcat mode 22000.](https://hashcat.net/wiki/doku.php?id=cracking_wpawpa2) 9 | > - [A write-up by **Ido Hoorvitch** from CyberArk covering the statistics of WPA/WPA2 password cracking.](https://www.cyberark.com/resources/threat-research-blog/cracking-wifi-at-scale-with-one-simple-trick) 10 | 11 | > [!WARNING] 12 | > This guide is for educational purposes only! 13 | > **Do not use hcxdumptool on networks you do not have permission to use it on!** 14 | > For more information regarding the specifics of this warning, refer to the [caution](https://github.com/ZerBea/hcxdumptool#caution) section of the README. 15 | 16 | ### Example Attack - Details/Goals 17 | 18 | This example will simulate attacking a single network of interest. 19 | It is assumed all information relating to the target is already known. 20 | 21 | ESSID of AP: **TestAP** 22 | MAC address of AP: **00c0cab035be**. 23 | AP channel: **11** 24 | 25 | ### Step One - Creating a BPF 26 | 27 | The creation of a [BPF](https://wiki.wireshark.org/CaptureFilters) is **mandatory** as it make hcxdumptool either _ignore_ the specified address, or _attack_ the specified address. 28 | 29 | The full command to create a BPF to _attack_ 00c0cab035be would be as follows: 30 | 31 | ``` 32 | hcxdumptool --bpfc="wlan addr1 00c0cab035be or wlan addr2 00c0cab035be or wlan addr3 00c0cab035be" >> attack.bpf 33 | ``` 34 | 35 | The full command to create a BPF to _protect_ 00c0cab035be would be as follows: 36 | 37 | ``` 38 | hcxdumptool --bpfc="not wlan addr3 00c0cab035be" >> protect.bpf 39 | ``` 40 | 41 | Since we are going to attack 00c0cab035be, we will use the **attack.bpf** filter. 42 | 43 | ### Step Two - Running hcxdumptool 44 | 45 | Since we have now made the BPF, we can start the attack using all the information mentioned above. 46 | 47 | ``` 48 | sudo hcxdumptool -i wlan0 -c 11a --bpf=attack.bpf -w TestAP.pcapng 49 | ``` 50 | 51 | > [!NOTE] 52 | > hcxdumptool **requires** either super user (root) privileges to run or the use of sudo! 53 | 54 | After running that command for a while, the output was as follows: 55 | 56 | ![hcxdumptool output](/docs/example-pic-1.png?raw=true "hcxdumptool TestAP output") 57 | 58 | ### Step Three - Conversion 59 | 60 | We now have a complete capture with all information needed for cracking the PSK. Before we crack the PSK, we need to convert it into a format Hashcat/JtR can understand using hcxpcapngtool. 61 | 62 | The command to do so is as follows: 63 | 64 | ``` 65 | hcxpcapngtool -o TestAP.hc22000 TestAP.pcapng 66 | ``` 67 | 68 | After running hcxpcapngtool, the output was as follows: 69 | 70 | ![hcxpcapngtool output](/docs/example-pic-2.png?raw=true "hcxpcapngtool output") 71 | 72 | > [!NOTE] 73 | > hcxpcapngtool will throw errors if: 74 | > 1. The capture was too short/incomplete. 75 | > 2. The format used is old/outdated. 76 | > 3. Too many DEAUTHENTICATION frames were detected. 77 | > 4. The capture file was cleaned. 78 | > 5. No PROBEREQUESTS were detected. 79 | > 6. Too few M1 frames were detected. 80 | 81 | ### Step Four - Cracking 82 | 83 | Finally, we have a Hashcat/JtR compatible format for cracking the PSK of our target network. For this example, we will use Hashcat for our cracking tool of choice. 84 | 85 | There are many different ways to use Hashcat but we will just use a straight dictionary attack. 86 | 87 | The command will be as follows: 88 | 89 | ``` 90 | sudo hashcat -a 0 -m 22000 ./TestAP.hc22000 ./Wordlists/probable.txt 91 | ``` 92 | 93 | After letting Hashcat run for a while, the output was as follows: 94 | 95 | ![Hashcat output](/docs/example-pic-3.png?raw=true "cracked Hashcat output") -------------------------------------------------------------------------------- /docs/gpiowait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZerBea/hcxdumptool/dabec8ac0c31b0a64d6f2387e6a420debf873258/docs/gpiowait.png -------------------------------------------------------------------------------- /docs/hardware-mod.md: -------------------------------------------------------------------------------- 1 | # Hardware Modification - See /docs For More Info 2 | 3 | When using this hardware modification, the LED will flash every 10 seconds if everything is fine and signals are received correctly. 4 | 5 | To terminate manually, press the push button for at least 10 seconds until LED turns on. (The LED will also turn on if hcxdumptool terminates.) 6 | 7 | Afterwards, the Raspberry Pi can be turned off and disconnected from it's power supply. 8 | -------------------------------------------------------------------------------- /docs/lessons_learned.txt: -------------------------------------------------------------------------------- 1 | Lessons learned (to be continued) 2 | -------------- 3 | 4 | a beautiful status output make the attack tool slow and sluggish 5 | 6 | too many features make an attack slow and sluggish 7 | 8 | response time behavior becomes very bad on big ringbuffers 9 | 10 | transmitting too many packets makes a channel busy 11 | 12 | a Raspberry Pi is not able to handle more than one interface at the same time 13 | 14 | multiple interfaces interfere with each other 15 | 16 | pselect doesn't like to be interrupted by another timer 17 | 18 | epoll is a better solution than pselect 19 | 20 | timerfd in combination with epoll is easier to handle than comparing timestamps 21 | 22 | active monitor require to set virtual MAC on interface - that is too slow 23 | 24 | setting a short preamble in radiotap header is ignored on tx 25 | 26 | entire AUTHENTICATION process should be done using a low data rate of 1.0 Mb/s and a low bandwidth 27 | 28 | there are (much) better ways than injecting stupid DEAUTHENTICATION frames to disconnect a CLIENT 29 | 30 | the most useful EAPOL frame is an EAPOL M2 frame(!) 31 | 32 | NL80211 provide a lot more features than WIRLESS EXTENSIONS 33 | 34 | NL80211 / RTNETLINK protocol can be used without libnl dependency 35 | 36 | sharing the interface (e.g. iw phy phy1 interface add mon0 type monitor) is counterproductive 37 | 38 | TX power is (completely) meaningless - RX sensitivity and a good antenna is all 39 | 40 | it is a thousand times faster using a Berkeley Packet Filter (BPF) than walking through endless filter lists 41 | -------------------------------------------------------------------------------- /docs/option-codes.md: -------------------------------------------------------------------------------- 1 | # PCAPNG Option Codes (Section Header Block) 2 | 3 | ENTERPRISE NUMBER: 0x2a, 0xce, 0x46, 0xa1 4 | 5 | MAGIC NUMBER: 0x2a, 0xce, 0x46, 0xa1, 0x79, 0xa0, 0x72, 0x33, 0x83, 0x37, 0x27, 0xab, 0x59, 0x33, 0xb3, 0x62, 0x45, 0x37, 0x11, 0x47, 0xa7, 0xcf, 0x32, 0x7f, 0x8d, 0x69, 0x80, 0xc0, 0x89, 0x5e, 0x5e, 0x98 6 | 7 | OPTIONCODE_MACMYORIG: 0xf29a (6 byte) 8 | 9 | OPTIONCODE_MACMYAP: 0xf29b (6 byte) 10 | 11 | OPTIONCODE_RC: 0xf29c (8 byte) 12 | 13 | OPTIONCODE_ANONCE: 0xf29d (32 byte) 14 | 15 | OPTIONCODE_MACMYSTA: 0xf29e (6 byte) 16 | 17 | OPTIONCODE_SNONCE: 0xf29f (32 byte) 18 | 19 | OPTIONCODE_WEAKCANDIDATE: 0xf2a0 (64 byte) == 63 characters + zero 20 | 21 | OPTIONCODE_GPS: 0xf2a1 (max 128 byte) 22 | -------------------------------------------------------------------------------- /hcxnmealog.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include "include/types.h" 31 | #include "include/byteorder.h" 32 | #include "include/ieee80211.h" 33 | #include "include/radiotap.h" 34 | #include "include/hcxnmealog.h" 35 | /*===========================================================================*/ 36 | /* global variable */ 37 | 38 | static int fd_socket_rx = 0; 39 | static int fd_gps = 0; 40 | static int fd_timer = 0; 41 | static int timerwaitnd = TIMER_EPWAITND; 42 | static int fix; 43 | static unsigned int nmeapacketcount = 0; 44 | static unsigned int packetcount = 0; 45 | static float latitude = 0; 46 | static float longitude = 0; 47 | static float altitude = 0; 48 | static float lat = 0; 49 | static float lon = 0; 50 | static float speed = 0; 51 | static float pdop = 0; 52 | static float hdop = 0; 53 | static float vdop = 0; 54 | static char ns = 0; 55 | static char ew = 0; 56 | static char altitudeunit = 0; 57 | static aplist_t *aplist = NULL; 58 | static FILE *fh_nmea = NULL; 59 | static FILE *fh_tsv = NULL; 60 | static ssize_t packetlen = 0; 61 | static ssize_t nmealen = 0; 62 | static u64 lifetime = 0; 63 | static u32 errorcount = 0; 64 | static u32 errorcountmax = ERROR_MAX; 65 | static u16 frequency = 0; 66 | static u16 ieee82011len = 0; 67 | static u16 payloadlen = 0; 68 | static u16 wanteventflag = 0; 69 | static u8 rssi = 0; 70 | static u8 *packetptr = NULL; 71 | static u8 *ieee82011ptr = NULL; 72 | static u8 *payloadptr = NULL; 73 | static ieee80211_mac_t *macfrx = NULL; 74 | static rth_t *rth = NULL; 75 | 76 | static char *encryptedstr = "encrypted"; 77 | static char *openstr = "open"; 78 | 79 | static struct tpacket_stats lStats = { 0 }; 80 | static socklen_t lStatsLength = sizeof(lStats); 81 | static struct sock_fprog bpf = { 0 }; 82 | static struct timespec tspecnmea = { 0 }; 83 | static struct timespec tspecakt = { 0 }; 84 | static char nmearxbuffer[NMEA_SIZE] = { 0 }; 85 | static char nmeaoutbuffer[NMEA_SIZE] = { 0 }; 86 | static u8 rx[PCAPNG_SNAPLEN * 2] = { 0 }; 87 | static u8 rxbuffer[PCAPNG_SNAPLEN * 2] = { 0 }; 88 | /*===========================================================================*/ 89 | static void close_devices() 90 | { 91 | if(fd_gps != 0) close(fd_gps); 92 | if(fd_socket_rx != 0) 93 | { 94 | if(getsockopt(fd_socket_rx, SOL_PACKET, PACKET_STATISTICS, &lStats, &lStatsLength) != 0) fprintf(stdout, "PACKET_STATISTICS failed\n"); 95 | close(fd_socket_rx); 96 | } 97 | return; 98 | } 99 | /*===========================================================================*/ 100 | static size_t chop(char *buffer, size_t len) 101 | { 102 | char *ptr = NULL; 103 | 104 | ptr = buffer +len - 1; 105 | while(len) 106 | { 107 | if(*ptr != '\n') break; 108 | *ptr-- = 0; 109 | len--; 110 | } 111 | while(len) 112 | { 113 | if(*ptr != '\r') break; 114 | *ptr-- = 0; 115 | len--; 116 | } 117 | return len; 118 | } 119 | /*---------------------------------------------------------------------------*/ 120 | static int fgetline(FILE *inputstream, size_t size, char *buffer) 121 | { 122 | size_t len = 0; 123 | char *buffptr = NULL; 124 | 125 | if(feof(inputstream)) return -1; 126 | buffptr = fgets(buffer, size, inputstream); 127 | if(buffptr == NULL) return -1; 128 | len = strlen(buffptr); 129 | len = chop(buffptr, len); 130 | return len; 131 | } 132 | /*===========================================================================*/ 133 | static bool read_bpf(char *bpfname) 134 | { 135 | static int len; 136 | static struct sock_filter *bpfptr; 137 | static FILE *fh_filter; 138 | static char linein[128]; 139 | 140 | if((fh_filter = fopen(bpfname, "r")) == NULL) return false; 141 | bpf.filter = (struct sock_filter*)calloc(BPF_MAXINSNS, sizeof(struct sock_filter)); 142 | bpf.len = 0; 143 | bpfptr = bpf.filter; 144 | while(bpf.len < BPF_MAXINSNS +1) 145 | { 146 | if((len = fgetline(fh_filter, 128, linein)) == -1) break; 147 | if(bpf.len == BPF_MAXINSNS) 148 | { 149 | bpf.len = 0; 150 | break; 151 | } 152 | if(len < 7) continue; 153 | if(linein[0] != '{') 154 | { 155 | if(sscanf(linein, "%" SCNu16 "%" SCNu8 "%" SCNu8 "%" SCNu32, &bpfptr->code, &bpfptr->jt, &bpfptr->jf, &bpfptr->k) != 4) 156 | { 157 | bpf.len = 0; 158 | break; 159 | } 160 | } 161 | else 162 | { 163 | if(sscanf(linein, "{ %" SCNx16 ", %" SCNu8 ", %" SCNu8 ", %" SCNx32 " },",&bpfptr->code, &bpfptr->jt, &bpfptr->jf, &bpfptr->k) != 4) 164 | { 165 | bpf.len = 0; 166 | break; 167 | } 168 | } 169 | bpfptr++; 170 | bpf.len++; 171 | } 172 | fclose(fh_filter); 173 | if(bpf.len == 0) return false; 174 | return true; 175 | } 176 | /*===========================================================================*/ 177 | static void close_files(void) 178 | { 179 | if(fh_nmea != NULL)fclose(fh_nmea); 180 | if(fh_tsv != NULL)fclose(fh_tsv); 181 | return; 182 | } 183 | /*---------------------------------------------------------------------------*/ 184 | static bool open_files(char *nmeaoutname, char *tsvoutname) 185 | { 186 | if(nmeaoutname != NULL) 187 | { 188 | if((fh_nmea = fopen(nmeaoutname, "a+")) == NULL) 189 | { 190 | errorcount++; 191 | fprintf(stderr, "failed to open NMEA file\n"); 192 | return false; 193 | } 194 | } 195 | if(tsvoutname != NULL) 196 | { 197 | if((fh_tsv = fopen(tsvoutname, "a+")) == NULL) 198 | { 199 | errorcount++; 200 | fprintf(stderr, "failed to open tSV file\n"); 201 | return false; 202 | } 203 | } 204 | return true; 205 | } 206 | /*===========================================================================*/ 207 | static bool open_socket_rx(int ifaktindex, char *bpfname) 208 | { 209 | static size_t c = 10; 210 | static struct sockaddr_ll saddr; 211 | static struct packet_mreq mrq; 212 | #if(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)) 213 | static int enable = 1; 214 | #endif 215 | static int socket_rx_flags; 216 | static int prioval; 217 | static socklen_t priolen; 218 | 219 | bpf.len = 0; 220 | if(bpfname != NULL) 221 | { 222 | if(read_bpf(bpfname) == false) 223 | { 224 | errorcount++; 225 | fprintf(stderr, "failed to read BPF\n"); 226 | return false; 227 | } 228 | } 229 | if((fd_socket_rx = socket(PF_PACKET, SOCK_RAW | SOCK_CLOEXEC, htons(ETH_P_ALL))) < 0) return false; 230 | memset(&mrq, 0, sizeof(mrq)); 231 | mrq.mr_ifindex = ifaktindex; 232 | mrq.mr_type = PACKET_MR_PROMISC; 233 | if(setsockopt(fd_socket_rx, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mrq, sizeof(mrq)) < 0) return false; 234 | priolen = sizeof(prioval); 235 | prioval = 20; 236 | if(setsockopt(fd_socket_rx, SOL_SOCKET, SO_PRIORITY, &prioval, priolen) < 0) return false; 237 | #if(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)) 238 | if(setsockopt(fd_socket_rx, SOL_PACKET, PACKET_IGNORE_OUTGOING, &enable, sizeof(int)) < 0) fprintf(stderr, "PACKET_IGNORE_OUTGOING is not supported by kernel\nfalling back to validate radiotap header length\n"); 239 | #endif 240 | if(bpf.len > 0) 241 | { 242 | if(setsockopt(fd_socket_rx, SOL_SOCKET, SO_ATTACH_FILTER, &bpf, sizeof(bpf)) < 0) 243 | { 244 | fprintf(stderr, "failed to attach BPF (SO_ATTACH_FILTER): %s\n", strerror(errno)); 245 | return false; 246 | } 247 | } 248 | memset(&saddr, 0, sizeof(saddr)); 249 | saddr.sll_family = PF_PACKET; 250 | saddr.sll_ifindex = ifaktindex; 251 | saddr.sll_protocol = htons(ETH_P_ALL); 252 | saddr.sll_halen = ETH_ALEN; 253 | saddr.sll_pkttype = PACKET_OTHERHOST; 254 | if(bind(fd_socket_rx, (struct sockaddr*) &saddr, sizeof(saddr)) < 0) return false; 255 | if((socket_rx_flags = fcntl(fd_socket_rx, F_GETFL, 0)) < 0) return false; 256 | if(fcntl(fd_socket_rx, F_SETFL, socket_rx_flags | O_NONBLOCK) < 0) return false; 257 | while((!wanteventflag) || (c != 0)) 258 | { 259 | packetlen = read(fd_socket_rx, rx, PCAPNG_SNAPLEN); 260 | if(packetlen == -1) break; 261 | c--; 262 | } 263 | return true; 264 | } 265 | /*---------------------------------------------------------------------------*/ 266 | static bool open_socket_gpsd(void) 267 | { 268 | static int socket_gps_flags; 269 | static struct sockaddr_in gpsd_addr; 270 | static const char *gpsd_enable_nmea = "?WATCH={\"enable\":true,\"json\":false,\"nmea\":true}"; 271 | 272 | if((fd_gps = socket(AF_INET, SOCK_STREAM, 0)) < 0) return false; 273 | memset(&gpsd_addr, 0, sizeof(struct sockaddr_in)); 274 | gpsd_addr.sin_family = AF_INET; 275 | gpsd_addr.sin_port = htons(2947); 276 | gpsd_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 277 | if(connect(fd_gps, (struct sockaddr*) &gpsd_addr, sizeof(gpsd_addr)) < 0) return false; 278 | if(fcntl(fd_gps, F_SETFL, socket_gps_flags | O_NONBLOCK) < 0) return false; 279 | if(write(fd_gps, gpsd_enable_nmea, 47) != 47) return false; 280 | return true; 281 | } 282 | /*---------------------------------------------------------------------------*/ 283 | static bool open_device_gps(char *gpsdevicename, int baudrate) 284 | { 285 | static struct termios tty; 286 | 287 | if((fd_gps = open(gpsdevicename, O_RDONLY | O_NONBLOCK)) < 0) return false; 288 | if(flock(fd_gps, LOCK_EX) < 0) return false; 289 | if(tcgetattr(fd_gps, &tty) < 0) return false; 290 | tty.c_cflag &= ~PARENB; // Clear parity bit, disabling parity (most common) 291 | tty.c_cflag &= ~CSTOPB; // Clear stop field, only one stop bit used in communication (most common) 292 | tty.c_cflag &= ~CSIZE; // Clear all bits that set the data size 293 | tty.c_cflag |= CS8; // 8 bits per byte (most common) 294 | tty.c_cflag &= ~CRTSCTS; // Disable RTS/CTS hardware flow control (most common) 295 | tty.c_cflag |= CREAD | CLOCAL; // Turn on READ & ignore ctrl lines (CLOCAL = 1) 296 | tty.c_lflag &= ~ICANON; 297 | tty.c_lflag &= ~ECHO; // Disable echo 298 | tty.c_lflag &= ~ECHOE; // Disable erasure 299 | tty.c_lflag &= ~ECHONL; // Disable new-line echo 300 | tty.c_lflag &= ~ISIG; // Disable interpretation of INTR, QUIT and SUSP 301 | tty.c_iflag &= ~(IXON | IXOFF | IXANY); // Turn off s/w flow ctrl 302 | tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL); // Disable any special handling of received bytes 303 | tty.c_oflag &= ~OPOST; // Prevent special interpretation of output bytes (e.g. newline chars) 304 | tty.c_oflag &= ~ONLCR; // Prevent conversion of newline to carriage return/line feed 305 | tty.c_cc[VTIME] = 10; // Wait for up to 1s (10 deciseconds), returning as soon as any data is received. 306 | tty.c_cc[VMIN] = 0; 307 | cfsetspeed(&tty, (speed_t)baudrate); 308 | if (tcsetattr(fd_gps, TCSANOW, &tty) < 0) return false; 309 | return true; 310 | } 311 | /*---------------------------------------------------------------------------*/ 312 | static bool open_devices(char *hcxnmealogname, int ifaktindex, char *bpfname, char *gpsdevice, int baudrate) 313 | { 314 | static char *gpsdname = "gpsd"; 315 | static char *devicename = "/dev"; 316 | 317 | if(ifaktindex != 0) 318 | { 319 | if(getuid() != 0) 320 | { 321 | errorcount++; 322 | fprintf(stderr, "%s must be run as root\n", hcxnmealogname); 323 | return false; 324 | } 325 | if(open_socket_rx(ifaktindex, bpfname) == false) 326 | { 327 | errorcount++; 328 | fprintf(stderr, "failed to open raw packet socket\n"); 329 | return false; 330 | } 331 | } 332 | if(strncmp(gpsdname, gpsdevice, 4) == 0) 333 | { 334 | if(open_socket_gpsd() == false) 335 | { 336 | fprintf(stderr, "failed to connect to GPSD\n"); 337 | return EXIT_SUCCESS; 338 | } 339 | } 340 | else if(strncmp(devicename, gpsdevice, 4) == 0) 341 | { 342 | if(open_device_gps(gpsdevice, baudrate) == false) 343 | { 344 | fprintf(stderr, "failed to open GPS device\n"); 345 | return EXIT_SUCCESS; 346 | } 347 | } 348 | else 349 | { 350 | fprintf(stderr, "no GPS device selected\n"); 351 | return EXIT_SUCCESS; 352 | } 353 | 354 | 355 | 356 | return true; 357 | } 358 | /*===========================================================================*/ 359 | /* SIGNALHANDLER */ 360 | static void signal_handler(int signum) 361 | { 362 | if((signum == SIGINT) || (signum == SIGTERM) || (signum == SIGKILL) || (signum == SIGTSTP)) wanteventflag |= EXIT_ON_SIGTERM; 363 | return; 364 | } 365 | /*---------------------------------------------------------------------------*/ 366 | static bool set_signal_handler(void) 367 | { 368 | struct sigaction sa; 369 | 370 | sa.sa_handler = signal_handler; 371 | sigemptyset(&sa.sa_mask); 372 | sa.sa_flags = SA_RESTART; 373 | if(sigaction(SIGINT, &sa, NULL) < 0) return false; 374 | if(sigaction(SIGTERM, &sa, NULL) < 0) return false; 375 | if(sigaction(SIGTSTP, &sa, NULL) < 0) return false; 376 | return true; 377 | } 378 | /*===========================================================================*/ 379 | /* TIMER */ 380 | static bool set_timer(void) 381 | { 382 | static struct itimerspec tval; 383 | 384 | if((fd_timer = timerfd_create(CLOCK_BOOTTIME, 0)) < 0) return false; 385 | tval.it_value.tv_sec = TIMER_VALUE_SEC; 386 | tval.it_value.tv_nsec = TIMER_VALUE_NSEC; 387 | tval.it_interval.tv_sec = TIMER_INTERVAL_SEC; 388 | tval.it_interval.tv_nsec = TIMER_INTERVAL_NSEC; 389 | if(timerfd_settime(fd_timer, 0, &tval, NULL) == -1) return false; 390 | return true; 391 | } 392 | /*===========================================================================*/ 393 | static void global_deinit() 394 | { 395 | static size_t i; 396 | 397 | if(fd_timer != 0) close(fd_timer); 398 | for(i = 0; i < APLIST_MAX; i++) 399 | { 400 | if((aplist + i)->apdata != NULL) free((aplist + i)->apdata); 401 | } 402 | if(aplist != NULL) free(aplist); 403 | return; 404 | } 405 | /*---------------------------------------------------------------------------*/ 406 | static bool global_init(void) 407 | { 408 | static size_t i; 409 | 410 | packetptr = rxbuffer; 411 | if(set_signal_handler() == false) 412 | { 413 | errorcount++; 414 | fprintf(stderr, "failed to initialize signal handler\n"); 415 | return false; 416 | } 417 | if(set_timer() == false) 418 | { 419 | errorcount++; 420 | fprintf(stderr, "failed to initialize timer\n"); 421 | return false; 422 | } 423 | 424 | if((aplist = (aplist_t*)calloc(APLIST_MAX, APLIST_SIZE)) == NULL) return false; 425 | for(i = 0; i < APLIST_MAX; i++) 426 | { 427 | if(((aplist + i)->apdata = (apdata_t*)calloc(1, APDATA_SIZE)) == NULL) return false; 428 | } 429 | 430 | return true; 431 | } 432 | static u8 cstou8(char *fptr) 433 | { 434 | static u8 idx0; 435 | static u8 idx1; 436 | static const u8 hashmap[] = 437 | { 438 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // 01234567 439 | 0x08, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 89:;<=>? 440 | 0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, // @ABCDEFG 441 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // HIJKLMNO 442 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // PQRSTUVW 443 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // XYZ[\]^_ 444 | 0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, // `abcdefg 445 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // hijklmno 446 | }; 447 | 448 | if(!isxdigit((unsigned char)fptr[0])) return 0; 449 | if(!isxdigit((unsigned char)fptr[1])) return 0; 450 | idx0 = ((u8)fptr[0] &0x1F) ^0x10; 451 | idx1 = ((u8)fptr[1] &0x1F) ^0x10; 452 | return (u8)(hashmap[idx0] <<4) | hashmap[idx1]; 453 | } 454 | /*===========================================================================*/ 455 | static int freq_to_channel(u32 freq) 456 | { 457 | if (freq == 2484) return 14; 458 | else if (freq < 2484) return (freq - 2407) / 5; 459 | else if (freq >= 4910 && freq <= 4980) return (freq - 4000) / 5; 460 | else if (freq < 5925) return (freq - 5000) / 5; 461 | else if (freq == 5935) return 2; 462 | else if (freq <= 45000) return (freq - 5950) / 5; 463 | else if (freq >= 58320 && freq <= 70200) return (freq - 56160) / 2160; 464 | return 0; 465 | } 466 | 467 | /*===========================================================================*/ 468 | static inline __attribute__((always_inline)) void process_nmea0183(void) 469 | { 470 | static int h; 471 | static int m; 472 | static int satcount; 473 | static u8 csc; 474 | static u8 csl; 475 | static float s; 476 | static float hdop1; 477 | static char v; 478 | static char *nsen; 479 | static char *nres; 480 | static size_t nl; 481 | static size_t np; 482 | static size_t cp; 483 | 484 | nmearxbuffer[nmealen] = 0; 485 | if((nmealen = read(fd_gps, nmearxbuffer, NMEA_SIZE)) < NMEA_MIN) 486 | { 487 | if(nmealen == - 1) errorcount++; 488 | return; 489 | } 490 | clock_gettime(CLOCK_REALTIME, &tspecnmea); 491 | nmearxbuffer[nmealen] = 0; 492 | nres = nmearxbuffer; 493 | while((nsen = strsep(&nres, "\n\r")) != NULL) 494 | { 495 | nl = strlen(nsen); 496 | if(nl < 6) continue; 497 | if(nsen[0] != '$') continue; 498 | if(nsen[nl -3] != '*') continue; 499 | csc = 0; 500 | for(cp = 1; cp < nl -3; cp ++) csc = csc ^ nsen[cp]; 501 | csl = cstou8(&nsen[nl -2]); 502 | if(csc != csl) continue; 503 | nmeapacketcount++; 504 | if(fh_nmea != NULL) fprintf(fh_nmea, "%s\n", nsen); 505 | if(nsen[3] == 'R') 506 | { 507 | if(nsen[4] == 'M') 508 | { 509 | if(nsen[5] == 'C') 510 | { 511 | latitude = 0; 512 | longitude = 0; 513 | ns = 0; 514 | ew = 0; 515 | sscanf(&nsen[7],"%02d%02d%f,%c,%f,%c,%f,%c,%f", &h, &m, &s, &v, &lat, &ew, &lon, &ns, &speed); 516 | if(lat != 0) latitude = ((int)lat) /100 + (((int)lat) %100 +lat -(int)lat)/60; 517 | if(lon != 0) longitude = ((int)lon) /100 + (((int)lon) %100 +lon -(int)lon)/60; 518 | if(ew == 'W') latitude =-latitude; 519 | if(ns == 'S') longitude =-longitude; 520 | } 521 | } 522 | } 523 | else if(nsen[3] == 'G') 524 | { 525 | if(nsen[4] == 'G') 526 | { 527 | if(nsen[5] == 'A') 528 | { 529 | latitude = 0; 530 | longitude = 0; 531 | altitude = 0; 532 | ns = 0; 533 | ew = 0; 534 | altitudeunit = 0; 535 | sscanf(&nsen[7],"%02d%02d%f,%f,%c,%f,%c,%d,%d,%f,%f,%c", &h, &m, &s, &lat, &ns, &lon, &ew, &fix, &satcount, &hdop1, &altitude, &altitudeunit); 536 | if(lat != 0) latitude = ((int)lat) /100 + (((int)lat) %100 +lat -(int)lat)/60; 537 | if(lon != 0) longitude = ((int)lon) /100 + (((int)lon) %100 +lon -(int)lon)/60; 538 | if(ew == 'S') latitude =-latitude; 539 | if(ns == 'w') longitude =-longitude; 540 | } 541 | } 542 | else if(nsen[4] == 'L') 543 | { 544 | if(nsen[5] == 'L') 545 | { 546 | latitude = 0; 547 | longitude = 0; 548 | ns = 0; 549 | ew = 0; 550 | sscanf(&nsen[7],"%f,%c,%f,%c,%02d%02d%f", &lat, &ew, &lon, &ns, &h, &m, &s); 551 | if(lat != 0) latitude = ((int)lat) /100 + (((int)lat) %100 +lat -(int)lat)/60; 552 | if(lon != 0) longitude = ((int)lon) /100 + (((int)lon) %100 +lon -(int)lon)/60; 553 | if(ew == 'W') latitude =-latitude; 554 | if(ns == 'S') longitude =-longitude; 555 | } 556 | } 557 | else if(nsen[4] == 'S') 558 | { 559 | if(nsen[5] == 'A') 560 | { 561 | pdop = 0; 562 | vdop = 0; 563 | hdop = 0; 564 | cp = 0; 565 | for(np = nl; np > 0; np--) 566 | { 567 | if(nsen[np] == ',') cp++; 568 | if(cp == 3) 569 | { 570 | sscanf(&nsen[np +1],"%f,%f,%f*", &pdop, &hdop, &vdop); 571 | } 572 | } 573 | } 574 | } 575 | } 576 | } 577 | if(fh_nmea != NULL) fflush(fh_nmea); 578 | if(fh_tsv != NULL) fflush(fh_tsv); 579 | return; 580 | } 581 | /*===========================================================================*/ 582 | static inline __attribute__((always_inline)) void write_tsv(int i) 583 | { 584 | if((aplist + i)->apdata->essid[0] != 0) fprintf(fh_tsv, "%lld\t%02x%02x%02x%02x%02x%02x\t%.*s\t%c%c\t%s\t%08x\t%08x\t%u\t%d\t%d\t%f\t%f\t%f%c\t%f\t%f\t%f\t%f\n", 585 | (long long)(aplist + i)->tsakt, 586 | macfrx->addr3[0], macfrx->addr3[1], macfrx->addr3[2], macfrx->addr3[3], macfrx->addr3[4], macfrx->addr3[5], (aplist + i)->apdata->essidlen, (aplist + i)->apdata->essid, (aplist + i)->apdata->country[0], (aplist + i)->apdata->country[1], 587 | (aplist + i)->apdata->encmode, (aplist + i)->apdata->rsnie, (aplist + i)->apdata->wpaie, 588 | (aplist + i)->apdata->frequency, (aplist + i)->apdata->channel,(s8)(aplist + i)->apdata->rssi, 589 | (aplist + i)->apdata->latitude, (aplist + i)->apdata->longitude, (aplist + i)->apdata->altitude, (aplist + i)->apdata->altitudeunit, (aplist + i)->apdata->speed, (aplist + i)->apdata->pdop, (aplist + i)->apdata->hdop, (aplist + i)->apdata->vdop); 590 | else fprintf(fh_tsv, "%lld\t%02x%02x%02x%02x%02x%02x\t\t%c%c\t%s\t%8u\t%08x\t%u\t%d\t%d\t%f\t%f\t%f%c\t%f\t%f\t%f\t%f\n", 591 | (long long)(aplist + i)->tsakt, 592 | macfrx->addr3[0], macfrx->addr3[1], macfrx->addr3[2], macfrx->addr3[3], macfrx->addr3[4], macfrx->addr3[5], (aplist + i)->apdata->essidlen, (aplist + i)->apdata->country[0], (aplist + i)->apdata->country[1], 593 | (aplist + i)->apdata->encmode, (aplist + i)->apdata->rsnie, (aplist + i)->apdata->wpaie, 594 | (aplist + i)->apdata->frequency, (aplist + i)->apdata->channel, (s8)(aplist + i)->apdata->rssi, 595 | (aplist + i)->apdata->latitude, (aplist + i)->apdata->longitude, (aplist + i)->apdata->altitude, (aplist + i)->apdata->altitudeunit, (aplist + i)->apdata->speed, (aplist + i)->apdata->pdop, (aplist + i)->apdata->hdop, (aplist + i)->apdata->vdop); 596 | return; 597 | } 598 | /*---------------------------------------------------------------------------*/ 599 | static inline __attribute__((always_inline)) void write_nmea(void) 600 | { 601 | static int cs; 602 | static size_t nl; 603 | static size_t cp; 604 | 605 | snprintf(nmeaoutbuffer, NMEA_SIZE, "$GPWPL,%10.5f,%c,%011.5f,%c,%02X%02X%02X%02X%02X%02X",lat, ew, lon, ns, macfrx->addr3[0], macfrx->addr3[1], macfrx->addr3[2], macfrx->addr3[3], macfrx->addr3[4], macfrx->addr3[5]); 606 | nl = strnlen(nmeaoutbuffer, NMEA_SIZE); 607 | cs = 0; 608 | for(cp = 1; cp < nl; cp++) cs = cs ^ nmeaoutbuffer[cp]; 609 | fprintf(fh_nmea, "%s*%02X\r\n", nmeaoutbuffer, cs); 610 | return; 611 | } 612 | /*---------------------------------------------------------------------------*/ 613 | static u8 get_radiotapfield(uint16_t rthlen) 614 | { 615 | static int i; 616 | static uint16_t pf; 617 | static rth_t *rth; 618 | static uint32_t *pp; 619 | 620 | rth = (rth_t*)packetptr; 621 | pf = RTHRX_SIZE; 622 | if((rth->it_present & IEEE80211_RADIOTAP_EXT) == IEEE80211_RADIOTAP_EXT) 623 | { 624 | pp = (uint32_t*)packetptr; 625 | for(i = 2; i < rthlen /4; i++) 626 | { 627 | #ifdef BIG_ENDIAN_HOST 628 | pp[i] = byte_swap_32(pp[i]); 629 | #endif 630 | pf += 4; 631 | if((pp[i] & IEEE80211_RADIOTAP_EXT) != IEEE80211_RADIOTAP_EXT) break; 632 | } 633 | } 634 | if((rth->it_present & IEEE80211_RADIOTAP_TSFT) == IEEE80211_RADIOTAP_TSFT) 635 | { 636 | if(pf > rthlen) return 0; 637 | if((pf %8) != 0) pf += 4; 638 | pf += 8; 639 | } 640 | if((rth->it_present & IEEE80211_RADIOTAP_FLAGS) == IEEE80211_RADIOTAP_FLAGS) 641 | { 642 | if(pf > rthlen) return 0; 643 | pf += 1; 644 | } 645 | if((rth->it_present & IEEE80211_RADIOTAP_RATE) == IEEE80211_RADIOTAP_RATE) pf += 1; 646 | if((rth->it_present & IEEE80211_RADIOTAP_CHANNEL) == IEEE80211_RADIOTAP_CHANNEL) 647 | { 648 | if(pf > rthlen) return 0; 649 | if((pf %2) != 0) pf += 1; 650 | frequency = (packetptr[pf +1] << 8) + packetptr[pf]; 651 | pf += 4; 652 | } 653 | if((rth->it_present & IEEE80211_RADIOTAP_FHSS) == IEEE80211_RADIOTAP_FHSS) 654 | { 655 | if((pf %2) != 0) pf += 1; 656 | pf += 2; 657 | } 658 | if((rth->it_present & IEEE80211_RADIOTAP_DBM_ANTSIGNAL) == IEEE80211_RADIOTAP_DBM_ANTSIGNAL) return packetptr[pf]; 659 | return 0; 660 | } 661 | /*---------------------------------------------------------------------------*/ 662 | static inline __attribute__((always_inline)) void get_wpaakm(apdata_t *apdata, u8 akmval) 663 | { 664 | if(akmval == 1) apdata->wpaie |= AKM_8021X; 665 | else if(akmval == 2) apdata->wpaie |= AKM_PSK; 666 | else if(akmval == 3) apdata->wpaie |= AKM_FT8021X; 667 | else if(akmval == 4) apdata->wpaie |= AKM_FTPSK; 668 | else if(akmval == 5) apdata->wpaie |= AKM_8021XSHA256; 669 | else if(akmval == 6) apdata->wpaie |= AKM_PSKSHA256; 670 | else if(akmval == 7) apdata->wpaie |= AKM_TDLS; 671 | else if(akmval == 8) apdata->wpaie |= AKM_SAESHA256; 672 | else if(akmval == 9) apdata->wpaie |= AKM_FTSAESHA256; 673 | else if(akmval == 10) apdata->wpaie |= AKM_APPKA; 674 | else if(akmval == 11) apdata->wpaie |= AKM_80211XBEAPSHA256; 675 | else if(akmval == 12) apdata->wpaie |= AKM_80211XBEAPSHA384; 676 | else if(akmval == 13) apdata->wpaie |= AKM_FT802xSHA384; 677 | else apdata->wpaie |= AKM_UNKNOWN; 678 | return; 679 | } 680 | /*---------------------------------------------------------------------------*/ 681 | static inline __attribute__((always_inline)) void get_wpacs(apdata_t *apdata, u8 csval) 682 | { 683 | if(csval == 1) apdata->wpaie |= CS_WEP; 684 | else if(csval == 2) apdata->wpaie |= CS_TKIP; 685 | else if(csval == 3) apdata->wpaie |= CS_RESERVED; 686 | else if(csval == 4) apdata->wpaie |= CS_CCMP128; 687 | else if(csval == 5) apdata->wpaie |= CS_WEP104; 688 | else if(csval == 6) apdata->wpaie |= CS_BIPCMAC128; 689 | else if(csval == 7) apdata->wpaie |= CS_GC_NOT_ALLOWED; 690 | else if(csval == 8) apdata->wpaie |= CS_GCMP128; 691 | else if(csval == 9) apdata->wpaie |= CS_GCMP256; 692 | else if(csval == 10) apdata->wpaie |= CS_CCMP256; 693 | else if(csval == 11) apdata->wpaie |= CS_BIPGMAC128; 694 | else if(csval == 12) apdata->wpaie |= CS_BIPGMAC256; 695 | else if(csval == 13) apdata->wpaie |= CS_BIPGMAC256; 696 | else apdata->wpaie |= CS_UNKNOWN; 697 | return; 698 | } 699 | /*---------------------------------------------------------------------------*/ 700 | static inline __attribute__((always_inline)) void get_rsnakm(apdata_t *apdata, u8 akmval) 701 | { 702 | if(akmval == 1) apdata->rsnie |= AKM_8021X; 703 | else if(akmval == 2) apdata->rsnie |= AKM_PSK; 704 | else if(akmval == 3) apdata->rsnie |= AKM_FT8021X; 705 | else if(akmval == 4) apdata->rsnie |= AKM_FTPSK; 706 | else if(akmval == 5) apdata->rsnie |= AKM_8021XSHA256; 707 | else if(akmval == 6) apdata->rsnie |= AKM_PSKSHA256; 708 | else if(akmval == 7) apdata->rsnie |= AKM_TDLS; 709 | else if(akmval == 8) apdata->rsnie |= AKM_SAESHA256; 710 | else if(akmval == 9) apdata->rsnie |= AKM_FTSAESHA256; 711 | else if(akmval == 10) apdata->rsnie |= AKM_APPKA; 712 | else if(akmval == 11) apdata->rsnie |= AKM_80211XBEAPSHA256; 713 | else if(akmval == 12) apdata->rsnie |= AKM_80211XBEAPSHA384; 714 | else if(akmval == 13) apdata->rsnie |= AKM_FT802xSHA384; 715 | else apdata->rsnie |= AKM_UNKNOWN; 716 | return; 717 | } 718 | /*---------------------------------------------------------------------------*/ 719 | static inline __attribute__((always_inline)) void get_rsncs(apdata_t *apdata, u8 csval) 720 | { 721 | if(csval == 1) apdata->rsnie |= CS_WEP; 722 | else if(csval == 2) apdata->rsnie |= CS_TKIP; 723 | else if(csval == 3) apdata->rsnie |= CS_RESERVED; 724 | else if(csval == 4) apdata->rsnie |= CS_CCMP128; 725 | else if(csval == 5) apdata->rsnie |= CS_WEP104; 726 | else if(csval == 6) apdata->rsnie |= CS_BIPCMAC128; 727 | else if(csval == 7) apdata->rsnie |= CS_GC_NOT_ALLOWED; 728 | else if(csval == 8) apdata->rsnie |= CS_GCMP128; 729 | else if(csval == 9) apdata->rsnie |= CS_GCMP256; 730 | else if(csval == 10) apdata->rsnie |= CS_CCMP256; 731 | else if(csval == 11) apdata->rsnie |= CS_BIPGMAC128; 732 | else if(csval == 12) apdata->rsnie |= CS_BIPGMAC256; 733 | else if(csval == 13) apdata->rsnie |= CS_BIPGMAC256; 734 | else apdata->rsnie |= CS_UNKNOWN; 735 | return; 736 | } 737 | /*---------------------------------------------------------------------------*/ 738 | static inline __attribute__((always_inline)) u16 get_tags(apdata_t *apdata, int infolen, u8 *infostart) 739 | { 740 | static ieee80211_ietag_t *infoptr; 741 | static ieee80211_suite_t *rsn; 742 | static ieee80211_suite_t *wpa; 743 | static u16 twstatus; 744 | static int tlen; 745 | static size_t i; 746 | 747 | twstatus = 0; 748 | while(0 < infolen) 749 | { 750 | infoptr = (ieee80211_ietag_t*)infostart; 751 | if(infolen < (int)(infoptr->len + IEEE80211_IETAG_SIZE)) return twstatus; 752 | if(infoptr->id == TAG_SSID) 753 | { 754 | if((infoptr->len > 0) && (infoptr->len <= ESSID_MAX)) 755 | { 756 | if(infoptr->len > 0) 757 | { 758 | if(infoptr->ie[0] != 0) 759 | { 760 | if((infoptr->len != apdata->essidlen) || (memcmp(infoptr->ie, apdata->essid, infoptr->len) != 0)) 761 | { 762 | twstatus |= TWSTATUS_ESSID; 763 | apdata->essidlen = infoptr->len; 764 | memcpy(apdata->essid, infoptr->ie, apdata->essidlen); 765 | } 766 | } 767 | else if(apdata->essid[0] == 0) 768 | { 769 | twstatus |= TWSTATUS_ESSID; 770 | apdata->essidlen = infoptr->len; 771 | memcpy(apdata->essid, infoptr->ie, apdata->essidlen); 772 | } 773 | } 774 | } 775 | } 776 | else if(infoptr->id == TAG_COUNTRY) 777 | { 778 | if(infoptr->len >= 6) 779 | { 780 | if((infoptr->ie[0] >= 'A') && (infoptr->ie[0] <= 'Z') && (infoptr->ie[1] >= 'A') && (infoptr->ie[1] <= 'Z')) 781 | { 782 | apdata->country[0] = infoptr->ie[0]; 783 | apdata->country[1] = infoptr->ie[1]; 784 | } 785 | } 786 | } 787 | else if(infoptr->id == TAG_RSN) 788 | { 789 | apdata->rsnie = 0; 790 | if(infoptr->len >= RSNLEN_MIN) 791 | { 792 | rsn = (ieee80211_suite_t*)infoptr->ie; 793 | if(__hcx16le(rsn->count) == 1) 794 | { 795 | if(memcmp(rsnccmp, rsn->suite, 3) == 0) 796 | { 797 | get_rsncs(apdata, infoptr->ie[5]); 798 | rsn += 1; 799 | tlen = 8; 800 | for(i = 0; i < __hcx16le(rsn->count); i++) 801 | { 802 | if(memcmp(rsnccmp, &infoptr->ie[tlen], 3) == 0) get_rsncs(apdata, infoptr->ie[tlen +3]); 803 | tlen += 4; 804 | if(tlen > infoptr->len) return 0; 805 | } 806 | rsn = (ieee80211_suite_t*)&infoptr->ie[tlen]; 807 | tlen += 2; 808 | for(i = 0; i < __hcx16le(rsn->count); i++) 809 | { 810 | if(memcmp(rsnpsk, &infoptr->ie[tlen], 3) == 0) get_rsnakm(apdata, infoptr->ie[tlen +3]); 811 | tlen += 4; 812 | if(tlen > infoptr->len) return 0; 813 | } 814 | } 815 | } 816 | } 817 | } 818 | else if(infoptr->id == TAG_VENDOR) 819 | { 820 | if(infoptr->len >= WPALEN_MIN) 821 | { 822 | if(memcmp(wpatype, infoptr->ie, SUITE_SIZE) == 0) 823 | { 824 | apdata->wpaie = 0; 825 | wpa = (ieee80211_suite_t*)(infoptr->ie +4); 826 | if(__hcx16le(wpa->count) == 1) 827 | { 828 | if(memcmp(wpatkip, wpa->suite, 3) == 0) 829 | { 830 | get_wpacs(apdata, infoptr->ie[3]); 831 | wpa += 1; 832 | tlen = 12; 833 | for(i = 0; i < __hcx16le(wpa->count); i++) 834 | { 835 | if(memcmp(wpaccmp, &infoptr->ie[tlen], 3) == 0) get_wpacs(apdata, infoptr->ie[tlen +3]); 836 | tlen += 4; 837 | if(tlen > infoptr->len) return 0; 838 | } 839 | wpa = (ieee80211_suite_t*)&infoptr->ie[tlen]; 840 | tlen += 2; 841 | for(i = 0; i < __hcx16le(wpa->count); i++) 842 | { 843 | if(memcmp(wpapsk, &infoptr->ie[tlen], 3) == 0) get_wpaakm(apdata, infoptr->ie[tlen +3]); 844 | tlen += 4; 845 | if(tlen > infoptr->len) return 0; 846 | } 847 | } 848 | } 849 | } 850 | } 851 | } 852 | infostart += infoptr->len + IEEE80211_IETAG_SIZE; 853 | infolen -= infoptr->len + IEEE80211_IETAG_SIZE; 854 | } 855 | return twstatus; 856 | } 857 | /*---------------------------------------------------------------------------*/ 858 | static inline __attribute__((always_inline)) void process80211beacon_proberesponse(void) 859 | { 860 | static int i; 861 | static ieee80211_beacon_proberesponse_t *beacon; 862 | static u16 beaconlen; 863 | static u16 twret; 864 | 865 | clock_gettime(CLOCK_REALTIME, &tspecakt); 866 | rssi = get_radiotapfield(__hcx16le(rth->it_len)); 867 | if(tspecakt.tv_sec != tspecnmea.tv_sec) return; 868 | if(fix == 0) return; 869 | if(lon == 0) return; 870 | if(lat == 0) return; 871 | if(rssi == 0) return; 872 | twret = 0; 873 | beacon = (ieee80211_beacon_proberesponse_t*)payloadptr; 874 | if((beaconlen = payloadlen - IEEE80211_BEACON_SIZE) < IEEE80211_IETAG_SIZE) return; 875 | for(i = 0; i < APLIST_MAX -1; i++) 876 | { 877 | if((aplist + i)->tsakt == 0) break; 878 | if(memcmp((aplist + i)->maca, macfrx->addr3, ETH_ALEN) != 0) continue; 879 | if((aplist + i)->tsakt == tspecakt.tv_sec) return; 880 | (aplist + i)->tsakt = tspecakt.tv_sec; 881 | if(__hcx16le(beacon->capability) & WLAN_CAPABILITY_PRIVACY) (aplist + i)->apdata->encmode = encryptedstr; 882 | else (aplist + i)->apdata->encmode = openstr; 883 | twret |= get_tags((aplist + i)->apdata, beaconlen, beacon->ie); 884 | if((aplist + i)->apdata->frequency != frequency) 885 | { 886 | (aplist + i)->apdata->frequency = frequency; 887 | twret |= TWSTATUS_FREQ; 888 | } 889 | if((aplist + i)->apdata->rssi < rssi) 890 | { 891 | (aplist + i)->apdata->rssi = rssi; 892 | twret |= TWSTATUS_RSSI; 893 | } 894 | if(twret > TWSTATUS_ERR) 895 | { 896 | if(fh_nmea != NULL) write_nmea(); 897 | if(fh_tsv != NULL) write_tsv(i); 898 | } 899 | return; 900 | } 901 | (aplist + i)->tsakt = tspecakt.tv_sec; 902 | memcpy((aplist + i)->maca, macfrx->addr3, ETH_ALEN); 903 | memset((aplist + i)->apdata, 0, APDATA_SIZE); 904 | (aplist + i)->apdata->frequency = frequency; 905 | (aplist + i)->apdata->channel = freq_to_channel(frequency); 906 | (aplist + i)->apdata->country[0] = '0'; 907 | (aplist + i)->apdata->country[1] = '0'; 908 | (aplist + i)->apdata->rssi = rssi; 909 | (aplist + i)->apdata->lat = lat; 910 | (aplist + i)->apdata->lon = lon; 911 | (aplist + i)->apdata->latitude = latitude; 912 | (aplist + i)->apdata->longitude = longitude; 913 | (aplist + i)->apdata->altitude = altitude; 914 | (aplist + i)->apdata->speed = speed; 915 | (aplist + i)->apdata->ns = ns; 916 | (aplist + i)->apdata->ew = ew; 917 | (aplist + i)->apdata->altitudeunit = altitudeunit; 918 | (aplist + i)->apdata->pdop = pdop; 919 | (aplist + i)->apdata->hdop = hdop; 920 | (aplist + i)->apdata->vdop = vdop; 921 | if(__hcx16le(beacon->capability) & WLAN_CAPABILITY_PRIVACY) (aplist + i)->apdata->encmode = encryptedstr; 922 | else (aplist + i)->apdata->encmode = openstr; 923 | twret = get_tags((aplist + i)->apdata, beaconlen, beacon->ie); 924 | if(fh_nmea != NULL) write_nmea(); 925 | if(fh_tsv != NULL) write_tsv(i); 926 | qsort(aplist, i + 1, APLIST_SIZE, sort_aplist_by_tsakt); 927 | return; 928 | } 929 | /*---------------------------------------------------------------------------*/ 930 | static inline __attribute__((always_inline)) void process_packet(void) 931 | { 932 | if((packetlen = read(fd_socket_rx, packetptr, PCAPNG_SNAPLEN)) < RTHRX_SIZE) 933 | { 934 | if(packetlen == -1) errorcount++; 935 | return; 936 | } 937 | rth = (rth_t*)packetptr; 938 | if((__hcx32le(rth->it_present) & IEEE80211_RADIOTAP_DBM_ANTSIGNAL) == 0) return; 939 | if(__hcx16le(rth->it_len) > packetlen) 940 | { 941 | errorcount++; 942 | return; 943 | } 944 | ieee82011ptr = packetptr + __hcx16le(rth->it_len); 945 | ieee82011len = packetlen - __hcx16le(rth->it_len); 946 | if(ieee82011len <= MAC_SIZE_RTS) return; 947 | macfrx = (ieee80211_mac_t*)ieee82011ptr; 948 | if((macfrx->from_ds == 1) && (macfrx->to_ds == 1)) 949 | { 950 | payloadptr = ieee82011ptr +MAC_SIZE_LONG; 951 | payloadlen = ieee82011len -MAC_SIZE_LONG; 952 | } 953 | else 954 | { 955 | payloadptr = ieee82011ptr +MAC_SIZE_NORM; 956 | payloadlen = ieee82011len -MAC_SIZE_NORM; 957 | } 958 | packetcount++; 959 | if(macfrx->type == IEEE80211_FTYPE_MGMT) 960 | { 961 | if((macfrx->subtype == IEEE80211_STYPE_BEACON) && (memcmp(macbc, macfrx->addr3, 6) == 0)) process80211beacon_proberesponse(); 962 | else if (macfrx->subtype == IEEE80211_STYPE_PROBE_RESP) process80211beacon_proberesponse(); 963 | } 964 | return; 965 | } 966 | /*===========================================================================*/ 967 | /* GPS LOOPs */ 968 | static bool gps_loop(char *basename, char *nmeaoutname) 969 | { 970 | static ssize_t i; 971 | static int fd_epoll = 0; 972 | static int epi = 0; 973 | static int epret = 0; 974 | static u64 timercount; 975 | static struct epoll_event ev, events[EPOLL_EVENTS_MAX]; 976 | 977 | if((fd_epoll= epoll_create(1)) < 0) return false; 978 | ev.data.fd = fd_gps; 979 | ev.events = EPOLLIN; 980 | if(epoll_ctl(fd_epoll, EPOLL_CTL_ADD, fd_gps, &ev) < 0) return false; 981 | epi++; 982 | 983 | ev.data.fd = fd_socket_rx; 984 | ev.events = EPOLLIN; 985 | if(epoll_ctl(fd_epoll, EPOLL_CTL_ADD, fd_socket_rx, &ev) < 0) return false; 986 | epi++; 987 | 988 | ev.data.fd = fd_timer; 989 | ev.events = EPOLLIN; 990 | if(epoll_ctl(fd_epoll, EPOLL_CTL_ADD, fd_timer, &ev) < 0) return false; 991 | epi++; 992 | 993 | fprintf(stdout, "\033[?25l"); 994 | if(nmeaoutname != NULL) fprintf(stdout, "%s %s logging NMEA 0183 track to %s\n", basename, VERSION_TAG, nmeaoutname); 995 | while(!wanteventflag) 996 | { 997 | if(errorcount > errorcountmax) wanteventflag |= EXIT_ON_ERROR; 998 | epret = epoll_pwait(fd_epoll, events, epi, timerwaitnd, NULL); 999 | if(epret == -1) 1000 | { 1001 | if(errno != EINTR) 1002 | { 1003 | errorcount++; 1004 | } 1005 | continue; 1006 | } 1007 | for(i = 0; i < epret; i++) 1008 | { 1009 | if(events[i].data.fd == fd_gps) process_nmea0183(); 1010 | else if(events[i].data.fd == fd_socket_rx) process_packet(); 1011 | else if(events[i].data.fd == fd_timer) 1012 | { 1013 | if(read(fd_timer, &timercount, sizeof(u64)) == -1) errorcount++; 1014 | lifetime++; 1015 | if((lifetime %10) == 0) 1016 | { 1017 | if(nmeaoutname != NULL) 1018 | { 1019 | fprintf(stdout, "\rNMEA 0183 sentences: %u (lat:%f lon:%f alt:%.1f) | 802.11 packets: %u", nmeapacketcount, latitude, longitude, altitude, packetcount); 1020 | fflush(stdout); 1021 | } 1022 | if(fh_nmea != NULL) fflush(fh_nmea); 1023 | if(fh_tsv != NULL) fflush(fh_tsv); 1024 | } 1025 | } 1026 | } 1027 | } 1028 | fprintf(stdout, "\n\033[?25h"); 1029 | return true; 1030 | } 1031 | /*===========================================================================*/ 1032 | __attribute__ ((noreturn)) 1033 | static void version(char *eigenname) 1034 | { 1035 | fprintf(stdout, "%s %s (C) %s ZeroBeat\n", eigenname, VERSION_TAG, VERSION_YEAR); 1036 | exit(EXIT_SUCCESS); 1037 | } 1038 | /*---------------------------------------------------------------------------*/ 1039 | __attribute__ ((noreturn)) 1040 | static inline void usage_additional(char *eigenname) 1041 | { 1042 | fprintf(stdout, "%s %s (C) %s ZeroBeat\n" 1043 | "Additional information:\n" 1044 | " 0x00000000 suite not in use\n" 1045 | "Cipher Suites (bitmask)\n" 1046 | " 0x00000001 WEP\n" 1047 | " 0x00000002 TKIP\n" 1048 | " 0x00000004 RESERVED\n" 1049 | " 0x00000008 CCMP-128\n" 1050 | " 0x00000010 WEP-104\n" 1051 | " 0x00000020 BIP-CMAC-128\n" 1052 | " 0x00000040 Group Address Traffic Not Allowed\n" 1053 | " 0x00000080 GCMP-128\n" 1054 | " 0x00000100 GCMP-256\n" 1055 | " 0x00000200 CCMP-256\n" 1056 | " 0x00000400 BIP-GMAC-128\n" 1057 | " 0x00000800 BIP-GMAC-256\n" 1058 | " 0x00001000 BIP-CMAC-256\n" 1059 | " 0x00008000 unknown\n" 1060 | "Authentication Management Suites (bitmask)\n" 1061 | " 0x00010000 802.1X\n" 1062 | " 0x00020000 PSK\n" 1063 | " 0x00040000 FT + 802.1X\n" 1064 | " 0x00080000 FT + PSK\n" 1065 | " 0x00100000 802.1X SHA-256\n" 1066 | " 0x00200000 PSK SHA-256\n" 1067 | " 0x00400000 TDLS\n" 1068 | " 0x00800000 SAE SHA-256\n" 1069 | " 0x01000000 FT + SAE SHA-256\n" 1070 | " 0x02000000 AP Peer Key Authentication\n" 1071 | " 0x04000000 802.1X Suite B EAP SH-256\n" 1072 | " 0x08000000 802.1X Suite B EAP SH-384\n" 1073 | " 0x10000000 FT + 802.1X SHA-384\n" 1074 | " 0x80000000 unknown\n" 1075 | "\n", eigenname, VERSION_TAG, VERSION_YEAR); 1076 | exit(EXIT_SUCCESS); 1077 | } 1078 | /*---------------------------------------------------------------------------*/ 1079 | __attribute__ ((noreturn)) 1080 | static void usage(char *eigenname) 1081 | { 1082 | fprintf(stdout, "%s %s (C) %s ZeroBeat\n" 1083 | "usage:\n" 1084 | "%s \n" 1085 | "\n" 1086 | "options:\n" 1087 | "-n : output nmea 0183 track to file\n" 1088 | " track append to file: filename\n" 1089 | " use gpsbabel to convert to other formats:\n" 1090 | " gpsbabel -w -t -i nmea -f in_file.nmea -o gpx -F out_file.gpx\n" 1091 | " gpsbabel -w -t -i nmea -f in_file.nmea -o kml -F out_file.kml\n" 1092 | " time = UTC (in accordance with the NMEA 0183 standard)\n" 1093 | "-t : output separated by tabulator (tsv)\n" 1094 | " columns:\n" 1095 | " LINUX EPOCH (seconds that have passed since the date January 1st, 1970)\n" 1096 | " use date -d @epoch_value to convert to human readable time\n" 1097 | " BSSID (MAC ACCESS POINT)\n" 1098 | " ESSID (network name)\n" 1099 | " COUNTRY CODE (ISO / IEC 3166 alpha2 country code)\n" 1100 | " ENCRYPTION (encrypted / open)\n" 1101 | " RSN INFORMATION ELEMENT (WPA2/WPA3)\n" 1102 | " bitmask (--help for more information)\n" 1103 | " WPA INFORMATION ELEMENT (WPA1)\n" 1104 | " bitmask (--help for more information)\n" 1105 | " FREQUENCY (interface frequency in MHz)\n" 1106 | " CHANNEL\n" 1107 | " RSSI (signal strength in dBm)\n" 1108 | " lATITUDE (decimal degrees)\n" 1109 | " LONGITUDE (decimal degrees)\n" 1110 | " ALTITUDE (decimal degrees)\n" 1111 | " SPEED (knots)\n" 1112 | " PDOP (position -3D- dilution of precision)\n" 1113 | " HDOP (horizontal dilution of precision)\n" 1114 | " VDOP (vertical dilution of precision)\n" 1115 | "-d : GPS source\n" 1116 | " use gpsd: gpsd\n" 1117 | " use device: /dev/ttyACM0, /dev/tty/USBx, ...\n" 1118 | " get more information: https://en.wikipedia.org/wiki/NMEA_0183\n" 1119 | " depending on the device it can take a while to get a fix\n" 1120 | "-b : baudrate of GPS device\n" 1121 | " default: 9600\n" 1122 | "-i : name of INTERFACE to be used\n" 1123 | "-h : show this help\n" 1124 | "-v : show version\n" 1125 | "\n" 1126 | "--bpf= : input Berkeley Packet Filter (BPF) code (maximum %d instructions) in tcpdump decimal numbers format\n" 1127 | " see --help for more information\n" 1128 | "--help : show additional help\n" 1129 | "--version : show version\n" 1130 | "\n", eigenname, VERSION_TAG, VERSION_YEAR, eigenname, BPF_MAXINSNS); 1131 | exit(EXIT_SUCCESS); 1132 | } 1133 | /*---------------------------------------------------------------------------*/ 1134 | __attribute__ ((noreturn)) 1135 | static void usageerror(char *eigenname) 1136 | { 1137 | fprintf(stdout, "%s %s (C) %s by ZeroBeat\n" 1138 | "usage: %s -h for help\n", eigenname, VERSION_TAG, VERSION_YEAR, eigenname); 1139 | exit(EXIT_FAILURE); 1140 | } 1141 | /*===========================================================================*/ 1142 | int main(int argc, char *argv[]) 1143 | { 1144 | static int auswahl; 1145 | static int index; 1146 | static int ifaktindex; 1147 | static int baudrate; 1148 | static char *gpsdevice; 1149 | static char *nmeaoutname; 1150 | static char *tsvoutname; 1151 | static char *bpfname; 1152 | 1153 | static const char *short_options = "n:t:d:b:i:hv"; 1154 | static const struct option long_options[] = 1155 | { 1156 | {"bpf", required_argument, NULL, HCX_BPF}, 1157 | {"version", no_argument, NULL, HCX_VERSION}, 1158 | {"help", no_argument, NULL, HCX_HELP_ADDITIONAL}, 1159 | {NULL, 0, NULL, 0} 1160 | }; 1161 | 1162 | auswahl = -1; 1163 | index = 0; 1164 | optind = 1; 1165 | optopt = 0; 1166 | baudrate = 9600; 1167 | ifaktindex = 0; 1168 | gpsdevice = NULL; 1169 | nmeaoutname = NULL; 1170 | tsvoutname = NULL; 1171 | bpfname = NULL; 1172 | 1173 | while((auswahl = getopt_long (argc, argv, short_options, long_options, &index)) != -1) 1174 | { 1175 | switch (auswahl) 1176 | { 1177 | case HCX_IFNAME: 1178 | if((ifaktindex = if_nametoindex(optarg)) == 0) 1179 | { 1180 | perror("failed to get interface index"); 1181 | exit(EXIT_FAILURE); 1182 | } 1183 | break; 1184 | 1185 | case HCX_BPF: 1186 | bpfname = optarg; 1187 | break; 1188 | 1189 | case HCX_GPS_DEVICE: 1190 | gpsdevice = optarg; 1191 | break; 1192 | 1193 | case HCX_GPS_BAUDRATE: 1194 | baudrate = atoi(optarg); 1195 | break; 1196 | 1197 | case HCX_OUTPUT_NMEA: 1198 | nmeaoutname = optarg; 1199 | break; 1200 | 1201 | case HCX_OUTPUT_TSV: 1202 | tsvoutname = optarg; 1203 | break; 1204 | 1205 | case HCX_HELP: 1206 | usage(basename(argv[0])); 1207 | break; 1208 | 1209 | case HCX_HELP_ADDITIONAL: 1210 | usage_additional(basename(argv[0])); 1211 | break; 1212 | 1213 | case HCX_VERSION: 1214 | version(basename(argv[0])); 1215 | break; 1216 | 1217 | case '?': 1218 | usageerror(basename(argv[0])); 1219 | break; 1220 | } 1221 | } 1222 | if(argc < 2) 1223 | { 1224 | fprintf(stderr, "no option selected\n"); 1225 | return EXIT_SUCCESS; 1226 | } 1227 | if(global_init() == false) goto byebye; 1228 | if(open_devices(basename(argv[0]), ifaktindex, bpfname, gpsdevice, baudrate) == false) goto byebye; 1229 | if(open_files(nmeaoutname, tsvoutname) == false) goto byebye; 1230 | 1231 | if(gps_loop(basename(argv[0]), nmeaoutname) == false) 1232 | { 1233 | errorcount++; 1234 | fprintf(stderr, "failed to initialize main scan loop\n"); 1235 | } 1236 | 1237 | byebye: 1238 | close_devices(); 1239 | close_files(); 1240 | global_deinit(); 1241 | 1242 | fprintf(stdout, "\nSummary:\n" 1243 | "-------\n" 1244 | "NMEA 0183 sentences received.....: %u\n" 1245 | "802.11 packets received by kernel: %u\n" 1246 | "802.11 packets dropped by kernel.: %u\n" 1247 | "\n", nmeapacketcount, lStats.tp_packets, lStats.tp_drops); 1248 | return EXIT_SUCCESS; 1249 | } 1250 | /*===========================================================================*/ 1251 | -------------------------------------------------------------------------------- /include/byteorder.h: -------------------------------------------------------------------------------- 1 | #ifndef __BYTE_ORDER 2 | # error "Please fix ENDIANESS " 3 | #endif 4 | /*===========================================================================*/ 5 | #define __hcxbswab16(x) \ 6 | ((u16)((((u16)(x) & (u16) 0x00ffU) << 8u) \ 7 | | (((u16)(x) & (u16) 0xff00U) >> 8u))) 8 | 9 | #define __hcxbswab32(x) \ 10 | ((u32)((((u32)(x) & (u32) 0x000000ffUL) << 24u) \ 11 | | (((u32)(x) & (u32) 0x0000ff00UL) << 8u) \ 12 | | (((u32)(x) & (u32) 0x00ff0000UL) >> 8u) \ 13 | | (((u32)(x) & (u32) 0xff000000UL) >> 24u))) 14 | 15 | #define __hcxbswab64(x) \ 16 | ((u64)((u64)(((u64)(x) & (u64) 0x00000000000000ffULL) << 56u) \ 17 | | (u64)(((u64)(x) & (u64) 0x000000000000ff00ULL) << 40u) \ 18 | | (u64)(((u64)(x) & (u64) 0x0000000000ff0000ULL) << 24u) \ 19 | | (u64)(((u64)(x) & (u64) 0x00000000ff000000ULL) << 8u) \ 20 | | (u64)(((u64)(x) & (u64) 0x000000ff00000000ULL) >> 8u) \ 21 | | (u64)(((u64)(x) & (u64) 0x0000ff0000000000ULL) >> 24u) \ 22 | | (u64)(((u64)(x) & (u64) 0x00ff000000000000ULL) >> 40u) \ 23 | | (u64)(((u64)(x) & (u64) 0xff00000000000000ULL) >> 56u))) 24 | /*---------------------------------------------------------------------------*/ 25 | #if __BYTE_ORDER == __LITTLE_ENDIAN 26 | #define __hcx16le(x) (u16)(x) 27 | #define __hcx32le(x) (u32)(x) 28 | #define __hcx64le(x) (u64)(x) 29 | #define __hcx16be(x) __hcxbswab16(x) 30 | #define __hcx32be(x) __hcxbswab32(x) 31 | #define __hcx64be(x) __hcxbswab64(x) 32 | #elif __BYTE_ORDER == __BIG_ENDIAN 33 | #define __hcx16le(x) __hcxbswab16(x) 34 | #define __hcx32le(x) __hcxbswab32(x) 35 | #define __hcx64le(x) __hcxbswab64(x) 36 | #define __hcx16be(x) (u16)(x) 37 | #define __hcx32be(x) (u32)(x) 38 | #define __hcx64be(x) (u64)(x) 39 | #endif 40 | /*===========================================================================*/ 41 | -------------------------------------------------------------------------------- /include/hcxdumptool.h: -------------------------------------------------------------------------------- 1 | /*===========================================================================*/ 2 | #define HCX_BPF 1 3 | #ifdef HCXWANTLIBPCAP 4 | #define HCX_BPFC 2 5 | #define HCX_BPFD 3 6 | #endif 7 | #define HCX_FTC 4 8 | #define HCX_TX_MAX 5 9 | #define HCX_GPIO_BUTTON 6 10 | #define HCX_GPIO_STATUSLED 7 11 | #define HCX_TOT 8 12 | #define HCX_ERROR_MAX 9 13 | #define HCX_DISABLE_DISASSOCIATION 10 14 | #define HCX_WATCHDOG_MAX 11 15 | #define HCX_M1M2ROGUE_MAX 12 16 | #define HCX_APCOUNT_MAX 13 17 | #define HCX_PRTX_MAX 14 18 | #define HCX_ON_SIGTERM 15 19 | #define HCX_ON_TOT 16 20 | #define HCX_ON_GPIOBUTTON 17 21 | #define HCX_ON_WATCHDOG 18 22 | #define HCX_EXIT_ON_EAPOL 19 23 | #define HCX_ON_ERROR 20 24 | #define HCX_ESSIDLIST 21 25 | #define HCX_RDS 22 26 | #define HCX_RDT 23 27 | #define HCX_RCASCAN 24 28 | #define HCX_IFNAME 'i' 29 | #define HCX_PCAPNGNAME 'w' 30 | #define HCX_INTERFACE_INFO 'I' 31 | #define HCX_SET_MONITORMODE 'm' 32 | #define HCX_SET_MONITORMODE_ACTIVE 'A' 33 | #define HCX_SET_SCANLIST_FROM_USER_CH 'c' 34 | #define HCX_SET_SCANLIST_FROM_USER_FREQ 'f' 35 | #define HCX_SET_SCANLIST_FROM_INTERFACE 'F' 36 | #define HCX_SHOW_INTERFACE_LIST 'L' 37 | #define HCX_SHOW_INTERFACE_LIST_SHORT 'l' 38 | #define HCX_HOLD_TIME 't' 39 | #define HCX_HELP 'h' 40 | #define HCX_HELP_ADDITIONAL 'H' 41 | #define HCX_VERSION 'v' 42 | /*---------------------------------------------------------------------------*/ 43 | #define HCX_DONE 1 44 | #define EXIT_ON_SIGTERM 0x0001 45 | #define EXIT_ON_GPIOBUTTON 0x0002 46 | #define EXIT_ON_TOT 0x0004 47 | #define EXIT_ON_WATCHDOG 0x0008 48 | #define EXIT_ON_EAPOL_PMKID 0x0010 49 | #define EXIT_ON_EAPOL_M3 0x0020 50 | #define EXIT_ON_EAPOL_M2 0x0040 51 | #define EXIT_ON_EAPOL_M2RG 0x0080 52 | #define EXIT_ON_EAPOL_M1 0x0100 53 | #define EXIT_ON_ERROR 0x0200 54 | 55 | #define EXIT_ACTION_REBOOT 0x01 56 | #define EXIT_ACTION_POWEROFF 0x02 57 | 58 | #define ERROR_MAX 100 59 | #define WATCHDOG_MAX 600 60 | #define CLIENTCOUNT_MAX 4 61 | #define APCOUNT_MAX 100 62 | 63 | #define IFTYPENL 0x01 64 | #define IFTYPEMON 0x02 65 | #define IFTYPEMONACT 0x04 66 | 67 | #define BPFD_HCX 0 68 | #define BPFD_TCPDUMP 1 69 | #define BPFD_C 2 70 | #define BPFD_ASM 3 71 | #define BPFD_DBG 4 72 | 73 | #define RCASCAN_ACTIVE 0x01 74 | #define RCASCAN_PASSIVE 0x02 75 | 76 | #define ETHTOOL_STD_LEN 32 77 | 78 | #define TIMER_EPWAITND 100 79 | #define TIMER1_VALUE_SEC 1L 80 | #define TIMER1_VALUE_NSEC 0L 81 | #define TIMER1_INTERVAL_SEC 1L 82 | #define TIMER1_INTERVAL_NSEC 0L 83 | #define EPOLL_EVENTS_MAX 5 84 | 85 | #define TIMEHOLD 5 86 | #define TSWAITEAPOLA 10000000UL 87 | #define TSSECOND1 1000000000ULL 88 | #define TSEAPOL1 50000000ULL 89 | #define TSEAPOL2 150000000ULL 90 | 91 | #define TSSECOND05 500000000ULL 92 | #define TSSECOND1 1000000000ULL 93 | #define TSSECOND2 2000000000ULL 94 | #define TSSECOND3 3000000000ULL 95 | #define TSSECOND4 4000000000ULL 96 | #define TSSECOND5 5000000000ULL 97 | #define TSSECOND6 6000000000ULL 98 | #define TSMINUTE1 60000000000ULL 99 | #define TSHOUR1 3600000000000ULL 100 | 101 | #define APLIST_MAX 250 102 | #define APLIST_HALF 125 103 | #define APDATA_MAX 100 104 | #define APRGLIST_MAX 1024 105 | #define APRGLIST_HALF 512 106 | #define CALIST_MAX 250 107 | #define CALIST_HALF 125 108 | 109 | #define OFFSETCHANNEL 0x0c 110 | #define OFFSETGCS 0x17 111 | #define OFFSETPCS 0x1d 112 | #define OFFSETAKM 0x23 113 | 114 | #define BCD_MAX 4095 115 | 116 | #define MACLIST_MAX 250 117 | #define ESSID_MAX 32 118 | #define PSK_MAX 64 119 | #define DRIVERNAME_MAX 32 120 | 121 | #define DRIVER_FORMAT 128 122 | #define DRIVER_LINK 128 123 | 124 | #define PROBERESPONSETX_MAX (APRGLIST_MAX - 1) 125 | 126 | #define PCAPNG_SNAPLEN 0x400 127 | 128 | #define TIMESTRING_LEN 128 129 | 130 | #define WLTXBUFFER 256 131 | 132 | #define NLTX_SIZE 0xfff 133 | #define NLRX_SIZE 0xffff 134 | 135 | #define WEAKCANDIDATEDEF "12345678" 136 | 137 | /*===========================================================================*/ 138 | /*===========================================================================*/ 139 | typedef struct __attribute__((__packed__)) 140 | { 141 | u64 tsauth; 142 | u64 tsassoc; 143 | u64 tsreassoc; 144 | u64 tsnull; 145 | u8 macc[ETH_ALEN]; 146 | u8 maca[ETH_ALEN]; 147 | int clientcount; 148 | u16 channel; 149 | u8 mic[16]; 150 | u8 essid[ESSID_MAX]; 151 | u8 essidlen; 152 | u8 akm; 153 | char m2; 154 | }cadata_t; 155 | #define CADATA_SIZE (sizeof(cadata_t)) 156 | /*---------------------------------------------------------------------------*/ 157 | typedef struct __attribute__((__packed__)) 158 | { 159 | u64 tsakt; 160 | cadata_t *cadata; 161 | }calist_t; 162 | #define CALIST_SIZE (sizeof(calist_t)) 163 | /*---------------------------------------------------------------------------*/ 164 | static int sort_calist_by_tsakt(const void *a, const void *b) 165 | { 166 | const calist_t *ai = (const calist_t *)a; 167 | const calist_t *bi = (const calist_t *)b; 168 | 169 | if(ai->tsakt < bi->tsakt) return 1; 170 | else if(ai->tsakt > bi->tsakt) return -1; 171 | return 0; 172 | } 173 | /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 174 | typedef struct __attribute__((__packed__)) 175 | { 176 | u64 tsrequest; 177 | u64 tsauthresponse; 178 | u64 tsassocresponse; 179 | u64 tsreassocresponse; 180 | u64 tsmacc; 181 | u64 tsm1; 182 | u64 tsm2; 183 | u64 tsm3; 184 | u64 tsresponse; 185 | u64 replaycount1; 186 | u64 replaycount2; 187 | u64 replaycount3; 188 | int apcount; 189 | u16 channel; 190 | u16 aid; 191 | u16 rtfrequency; 192 | u8 rtrssi; 193 | u8 nonce[4]; 194 | u8 rsnpmkid[PMKID_MAX]; 195 | u8 maca[ETH_ALEN]; 196 | u8 macc[ETH_ALEN]; 197 | u8 essid[ESSID_MAX]; 198 | u8 essidlen; 199 | u8 opensystem; 200 | u8 gcs; 201 | u8 pcs; 202 | u8 akm; 203 | u8 mcs; 204 | u8 ucs; 205 | u8 akm1; 206 | u8 mfp; 207 | u8 akmstat; 208 | char privacy; 209 | char pmkid; 210 | char m1; 211 | char m1m2; 212 | char m1m2m3; 213 | bool beacon; 214 | bool proberesponse; 215 | bool suthentication; 216 | bool associationresponse; 217 | bool reassociationresponse; 218 | }apdata_t; 219 | #define APDATA_SIZE (sizeof(apdata_t)) 220 | /*---------------------------------------------------------------------------*/ 221 | typedef struct __attribute__((__packed__)) 222 | { 223 | u64 tsakt; 224 | apdata_t *apdata; 225 | }aplist_t; 226 | #define APLIST_SIZE (sizeof(aplist_t)) 227 | /*---------------------------------------------------------------------------*/ 228 | static int sort_aplist_by_tsakt(const void *a, const void *b) 229 | { 230 | const aplist_t *ai = (const aplist_t *)a; 231 | const aplist_t *bi = (const aplist_t *)b; 232 | 233 | if(ai->tsakt < bi->tsakt) return 1; 234 | else if(ai->tsakt > bi->tsakt) return -1; 235 | return 0; 236 | } 237 | /*---------------------------------------------------------------------------*/ 238 | static int sort_aplist_by_tsresponse(const void *a, const void *b) 239 | { 240 | const aplist_t *ai = (const aplist_t *)a; 241 | const aplist_t *bi = (const aplist_t *)b; 242 | 243 | if(ai->apdata->tsresponse < bi->apdata->tsresponse) return 1; 244 | else if(ai->apdata->tsresponse > bi->apdata->tsresponse) return -1; 245 | return 0; 246 | } 247 | /*---------------------------------------------------------------------------*/ 248 | static int sort_aplist_by_rtrssi(const void *a, const void *b) 249 | { 250 | const aplist_t *ai = (const aplist_t *)a; 251 | const aplist_t *bi = (const aplist_t *)b; 252 | 253 | if(ai->apdata->rtrssi < bi->apdata->rtrssi) return 1; 254 | else if(ai->apdata->rtrssi > bi->apdata->rtrssi) return -1; 255 | return 0; 256 | } 257 | /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 258 | /*---------------------------------------------------------------------------*/ 259 | #define SCANLIST_MAX 512 260 | #define FREQUENCYLIST_MAX 256 261 | typedef struct __attribute__((__packed__)) 262 | { 263 | u32 frequency; 264 | u32 channel; 265 | u32 pwr; 266 | #define IF_STAT_FREQ_DISABLED 0x01 267 | u8 status; 268 | }frequencylist_t; 269 | #define FREQUENCYLIST_SIZE (sizeof(frequencylist_t)) 270 | /*---------------------------------------------------------------------------*/ 271 | #define INTERFACELIST_MAX 64 272 | typedef struct __attribute__((__packed__)) 273 | { 274 | int index; 275 | int wiphy; 276 | u64 wdev; 277 | #define IF_HAS_NETLINK 0x01 278 | #define IF_HAS_MONITOR 0x02 279 | #define IF_HAS_MONITOR_ACTIVE 0x04 280 | #define IF_HAS_NLMON 0x03 281 | #define IF_HAS_NLMON_ACTIVE 0x07 282 | #define IF_IS_SHARED 0x08 283 | u8 type; 284 | #define IF_STAT_MONITOR 0x01 285 | #define IF_STAT_UP 0x02 286 | #define IF_STAT_OK 0x03 287 | u8 status; 288 | u8 hwmac[6]; 289 | u8 vimac[6]; 290 | char name[IFNAMSIZ +1]; 291 | char driver[DRIVERNAME_MAX]; 292 | size_t i; 293 | frequencylist_t *frequencylist; 294 | }interface_t; 295 | #define INTERFACELIST_SIZE (sizeof(interface_t)) 296 | 297 | static int sort_interfacelist_by_wiphy(const void *a, const void *b) 298 | { 299 | const interface_t *ia = (const interface_t *)a; 300 | const interface_t *ib = (const interface_t *)b; 301 | 302 | if(ia->wiphy > ib->wiphy) return 1; 303 | else if(ia->wiphy < ib->wiphy) return -1; 304 | return 0; 305 | } 306 | /*===========================================================================*/ 307 | typedef struct 308 | { 309 | struct nlmsghdr nlh; 310 | struct ifinfomsg ifinfo; 311 | char attrbuf[512]; 312 | }req_t; 313 | /*===========================================================================*/ 314 | static bool read_bpf(char *bpfname); 315 | static inline bool nl_set_frequency(void); 316 | /*===========================================================================*/ 317 | -------------------------------------------------------------------------------- /include/hcxlabtool.h: -------------------------------------------------------------------------------- 1 | /*===========================================================================*/ 2 | #define HCX_BPF 1 3 | #ifdef HCXWANTLIBPCAP 4 | #define HCX_BPFC 2 5 | #define HCX_BPFD 3 6 | #endif 7 | #define HCX_FTC 4 8 | #define HCX_TX_MAX 5 9 | #define HCX_GPIO_BUTTON 6 10 | #define HCX_GPIO_STATUSLED 7 11 | #define HCX_TOT 8 12 | #define HCX_ERROR_MAX 9 13 | #define HCX_DISABLE_DISASSOCIATION 10 14 | #define HCX_WATCHDOG_MAX 11 15 | #define HCX_M1M2ROGUE_MAX 12 16 | #define HCX_APCOUNT_MAX 13 17 | #define HCX_PRTX_MAX 14 18 | #define HCX_ON_SIGTERM 15 19 | #define HCX_ON_TOT 16 20 | #define HCX_ON_GPIOBUTTON 17 21 | #define HCX_ON_WATCHDOG 18 22 | #define HCX_EXIT_ON_EAPOL 19 23 | #define HCX_ON_ERROR 20 24 | #define HCX_ESSIDLIST 21 25 | #define HCX_RDS 22 26 | #define HCX_RCASCAN 23 27 | #define HCX_IFNAME 'i' 28 | #define HCX_PCAPNGNAME 'w' 29 | #define HCX_INTERFACE_INFO 'I' 30 | #define HCX_SET_MONITORMODE 'm' 31 | #define HCX_SET_MONITORMODE_ACTIVE 'A' 32 | #define HCX_SET_SCANLIST_FROM_USER_CH 'c' 33 | #define HCX_SET_SCANLIST_FROM_USER_FREQ 'f' 34 | #define HCX_SET_SCANLIST_FROM_INTERFACE 'F' 35 | #define HCX_SHOW_INTERFACE_LIST 'L' 36 | #define HCX_SHOW_INTERFACE_LIST_SHORT 'l' 37 | #define HCX_HOLD_TIME 't' 38 | #define HCX_HELP 'h' 39 | #define HCX_HELP_ADDITIONAL 'H' 40 | #define HCX_VERSION 'v' 41 | /*---------------------------------------------------------------------------*/ 42 | #define HCX_DONE 1 43 | #define EXIT_ON_SIGTERM 0x0001 44 | #define EXIT_ON_GPIOBUTTON 0x0002 45 | #define EXIT_ON_TOT 0x0004 46 | #define EXIT_ON_WATCHDOG 0x0008 47 | #define EXIT_ON_EAPOL_PMKID 0x0010 48 | #define EXIT_ON_EAPOL_M3 0x0020 49 | #define EXIT_ON_EAPOL_M2 0x0040 50 | #define EXIT_ON_EAPOL_M2RG 0x0080 51 | #define EXIT_ON_EAPOL_M1 0x0100 52 | #define EXIT_ON_ERROR 0x0200 53 | 54 | #define EXIT_ACTION_REBOOT 0x01 55 | #define EXIT_ACTION_POWEROFF 0x02 56 | 57 | #define ERROR_MAX 100 58 | #define WATCHDOG_MAX 600 59 | #define CLIENTCOUNT_MAX 4 60 | #define APCOUNT_MAX 100 61 | 62 | #define IFTYPENL 0x01 63 | #define IFTYPEMON 0x02 64 | #define IFTYPEMONACT 0x04 65 | 66 | #define BPFD_HCX 0 67 | #define BPFD_TCPDUMP 1 68 | #define BPFD_C 2 69 | #define BPFD_ASM 3 70 | #define BPFD_DBG 4 71 | 72 | #define RCASCAN_ACTIVE 0x01 73 | #define RCASCAN_PASSIVE 0x02 74 | 75 | #define ETHTOOL_STD_LEN 32 76 | 77 | #define TIMER_EPWAITND 100 78 | #define TIMER1_VALUE_SEC 1L 79 | #define TIMER1_VALUE_NSEC 0L 80 | #define TIMER1_INTERVAL_SEC 1L 81 | #define TIMER1_INTERVAL_NSEC 0L 82 | #define EPOLL_EVENTS_MAX 5 83 | 84 | #define TIMEHOLD 7 85 | #define TSWAITEAPOLA 10000000UL 86 | #define TSSECOND1 1000000000ULL 87 | #define TSEAPOL1 50000000ULL 88 | #define TSEAPOL2 150000000ULL 89 | 90 | #define TSSECOND05 500000000ULL 91 | #define TSSECOND1 1000000000ULL 92 | #define TSSECOND2 2000000000ULL 93 | #define TSSECOND3 3000000000ULL 94 | #define TSSECOND4 4000000000ULL 95 | #define TSSECOND5 5000000000ULL 96 | #define TSSECOND6 6000000000ULL 97 | #define TSMINUTE1 60000000000ULL 98 | #define TSHOUR1 3600000000000ULL 99 | 100 | #define APLIST_MAX 250 101 | #define APLIST_HALF 125 102 | #define APDATA_MAX 100 103 | #define APRGLIST_MAX 1024 104 | #define APRGLIST_HALF 512 105 | #define CALIST_MAX 250 106 | #define CALIST_HALF 125 107 | 108 | #define OFFSETCHANNEL 0x0c 109 | #define OFFSETGCS 0x17 110 | #define OFFSETPCS 0x1d 111 | #define OFFSETAKM 0x23 112 | 113 | #define BCD_MAX 4095 114 | 115 | #define MACLIST_MAX 250 116 | #define ESSID_MAX 32 117 | #define PSK_MAX 64 118 | #define DRIVERNAME_MAX 32 119 | 120 | #define DRIVER_FORMAT 128 121 | #define DRIVER_LINK 128 122 | 123 | #define PROBERESPONSETX_MAX (APRGLIST_MAX - 1) 124 | 125 | #define PCAPNG_SNAPLEN 0x400 126 | 127 | #define TIMESTRING_LEN 128 128 | 129 | #define WLTXBUFFER 256 130 | 131 | #define NLTX_SIZE 0xfff 132 | #define NLRX_SIZE 0xffff 133 | 134 | #define WEAKCANDIDATEDEF "12345678" 135 | 136 | /*===========================================================================*/ 137 | /*===========================================================================*/ 138 | typedef struct __attribute__((__packed__)) 139 | { 140 | u64 tsauth; 141 | u64 tsassoc; 142 | u64 tsreassoc; 143 | u64 tsnull; 144 | u8 macc[ETH_ALEN]; 145 | u8 maca[ETH_ALEN]; 146 | int clientcount; 147 | u16 channel; 148 | u8 mic[16]; 149 | u8 essid[ESSID_MAX]; 150 | u8 essidlen; 151 | u8 akm; 152 | char m2; 153 | }cadata_t; 154 | #define CADATA_SIZE (sizeof(cadata_t)) 155 | /*---------------------------------------------------------------------------*/ 156 | typedef struct __attribute__((__packed__)) 157 | { 158 | u64 tsakt; 159 | cadata_t *cadata; 160 | }calist_t; 161 | #define CALIST_SIZE (sizeof(calist_t)) 162 | /*---------------------------------------------------------------------------*/ 163 | static int sort_calist_by_tsakt(const void *a, const void *b) 164 | { 165 | const calist_t *ai = (const calist_t *)a; 166 | const calist_t *bi = (const calist_t *)b; 167 | 168 | if(ai->tsakt < bi->tsakt) return 1; 169 | else if(ai->tsakt > bi->tsakt) return -1; 170 | return 0; 171 | } 172 | /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 173 | typedef struct __attribute__((__packed__)) 174 | { 175 | u64 tsrequest; 176 | u64 tsauthresponse; 177 | u64 tsassocresponse; 178 | u64 tsreassocresponse; 179 | u64 tsmacc; 180 | u64 tsm1; 181 | u64 tsm2; 182 | u64 tsm3; 183 | u64 tsresponse; 184 | u64 replaycount1; 185 | u64 replaycount2; 186 | u64 replaycount3; 187 | int apcount; 188 | u16 channel; 189 | u16 aid; 190 | u16 rtfrequency; 191 | u8 rtrssi; 192 | u8 nonce[4]; 193 | u8 rsnpmkid[PMKID_MAX]; 194 | u8 maca[ETH_ALEN]; 195 | u8 macc[ETH_ALEN]; 196 | u8 essid[ESSID_MAX]; 197 | u8 essidlen; 198 | u8 opensystem; 199 | u8 gcs; 200 | u8 pcs; 201 | u8 akm; 202 | u8 mcs; 203 | u8 ucs; 204 | u8 akm1; 205 | u8 mfp; 206 | u8 akmstat; 207 | char privacy; 208 | char pmkid; 209 | char m1; 210 | char m1m2; 211 | char m1m2m3; 212 | bool beacon; 213 | bool proberesponse; 214 | bool suthentication; 215 | bool associationresponse; 216 | bool reassociationresponse; 217 | }apdata_t; 218 | #define APDATA_SIZE (sizeof(apdata_t)) 219 | /*---------------------------------------------------------------------------*/ 220 | typedef struct __attribute__((__packed__)) 221 | { 222 | u64 tsakt; 223 | apdata_t *apdata; 224 | }aplist_t; 225 | #define APLIST_SIZE (sizeof(aplist_t)) 226 | /*---------------------------------------------------------------------------*/ 227 | static int sort_aplist_by_tsakt(const void *a, const void *b) 228 | { 229 | const aplist_t *ai = (const aplist_t *)a; 230 | const aplist_t *bi = (const aplist_t *)b; 231 | 232 | if(ai->tsakt < bi->tsakt) return 1; 233 | else if(ai->tsakt > bi->tsakt) return -1; 234 | return 0; 235 | } 236 | /*---------------------------------------------------------------------------*/ 237 | static int sort_aplist_by_tsresponse(const void *a, const void *b) 238 | { 239 | const aplist_t *ai = (const aplist_t *)a; 240 | const aplist_t *bi = (const aplist_t *)b; 241 | 242 | if(ai->apdata->tsresponse < bi->apdata->tsresponse) return 1; 243 | else if(ai->apdata->tsresponse > bi->apdata->tsresponse) return -1; 244 | return 0; 245 | } 246 | /*---------------------------------------------------------------------------*/ 247 | static int sort_aplist_by_rtrssi(const void *a, const void *b) 248 | { 249 | const aplist_t *ai = (const aplist_t *)a; 250 | const aplist_t *bi = (const aplist_t *)b; 251 | 252 | if(ai->apdata->rtrssi < bi->apdata->rtrssi) return 1; 253 | else if(ai->apdata->rtrssi > bi->apdata->rtrssi) return -1; 254 | return 0; 255 | } 256 | /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 257 | /*---------------------------------------------------------------------------*/ 258 | #define SCANLIST_MAX 512 259 | #define FREQUENCYLIST_MAX 256 260 | typedef struct __attribute__((__packed__)) 261 | { 262 | u32 frequency; 263 | u32 channel; 264 | u32 pwr; 265 | #define IF_STAT_FREQ_DISABLED 0x01 266 | u8 status; 267 | }frequencylist_t; 268 | #define FREQUENCYLIST_SIZE (sizeof(frequencylist_t)) 269 | /*---------------------------------------------------------------------------*/ 270 | #define INTERFACELIST_MAX 64 271 | typedef struct __attribute__((__packed__)) 272 | { 273 | int index; 274 | int wiphy; 275 | u64 wdev; 276 | #define IF_HAS_NETLINK 0x01 277 | #define IF_HAS_MONITOR 0x02 278 | #define IF_HAS_MONITOR_ACTIVE 0x04 279 | #define IF_HAS_NLMON 0x03 280 | #define IF_HAS_NLMON_ACTIVE 0x07 281 | #define IF_IS_SHARED 0x08 282 | u8 type; 283 | #define IF_STAT_MONITOR 0x01 284 | #define IF_STAT_UP 0x02 285 | #define IF_STAT_OK 0x03 286 | u8 status; 287 | u8 hwmac[6]; 288 | u8 vimac[6]; 289 | char name[IFNAMSIZ +1]; 290 | char driver[DRIVERNAME_MAX]; 291 | size_t i; 292 | frequencylist_t *frequencylist; 293 | }interface_t; 294 | #define INTERFACELIST_SIZE (sizeof(interface_t)) 295 | 296 | static int sort_interfacelist_by_wiphy(const void *a, const void *b) 297 | { 298 | const interface_t *ia = (const interface_t *)a; 299 | const interface_t *ib = (const interface_t *)b; 300 | 301 | if(ia->wiphy > ib->wiphy) return 1; 302 | else if(ia->wiphy < ib->wiphy) return -1; 303 | return 0; 304 | } 305 | /*===========================================================================*/ 306 | typedef struct 307 | { 308 | struct nlmsghdr nlh; 309 | struct ifinfomsg ifinfo; 310 | char attrbuf[512]; 311 | }req_t; 312 | /*===========================================================================*/ 313 | static bool read_bpf(char *bpfname); 314 | static inline bool nl_set_frequency(void); 315 | /*===========================================================================*/ 316 | -------------------------------------------------------------------------------- /include/hcxnmealog.h: -------------------------------------------------------------------------------- 1 | #define HCX_OUTPUT_NMEA 'n' 2 | #define HCX_OUTPUT_TSV 't' 3 | #define HCX_GPS_DEVICE 'd' 4 | #define HCX_GPS_BAUDRATE 'b' 5 | #define HCX_IFNAME 'i' 6 | #define HCX_BPF 1 7 | 8 | #define HCX_HELP 'h' 9 | #define HCX_HELP_ADDITIONAL 'H' 10 | #define HCX_VERSION 'v' 11 | 12 | #define ERROR_MAX 100 13 | 14 | #define NMEA_MIN 10 15 | #define NMEA_SIZE 2048 16 | #define NMEA_FIELD_SIZE 20 17 | #define NMEA_FIELD_MAX 20 18 | 19 | #define EXIT_ON_SIGTERM 0x0001 20 | #define EXIT_ON_ERROR 0x0100 21 | 22 | #define TIMER_EPWAITND 100 23 | #define EPOLL_EVENTS_MAX 5 24 | #define TIMER_VALUE_SEC 1L 25 | #define TIMER_VALUE_NSEC 0L 26 | #define TIMER_INTERVAL_SEC 1L 27 | #define TIMER_INTERVAL_NSEC 0L 28 | #define PCAPNG_SNAPLEN 0x400 29 | 30 | #define TIMESTRING_LEN 128 31 | #define ESSID_MAX 32 32 | 33 | #define APLIST_MAX 1024 34 | 35 | #define TWSTATUS_ERR 0x0001 36 | #define TWSTATUS_ESSID 0x0002 37 | #define TWSTATUS_FREQ 0x0003 38 | #define TWSTATUS_RSSI 0x0008 39 | /*---------------------------------------------------------------------------*/ 40 | typedef struct __attribute__((__packed__)) 41 | { 42 | float lat; 43 | float lon; 44 | float latitude; 45 | float longitude; 46 | float altitude; 47 | float speed; 48 | float pdop; 49 | float hdop; 50 | float vdop; 51 | char ns; 52 | char ew; 53 | char altitudeunit; 54 | int channel; 55 | #define CS_WEP 0x00000001 56 | #define CS_TKIP 0x00000002 57 | #define CS_RESERVED 0x00000004 58 | #define CS_CCMP128 0x00000008 59 | #define CS_WEP104 0x00000010 60 | #define CS_BIPCMAC128 0x00000020 61 | #define CS_GC_NOT_ALLOWED 0x00000040 62 | #define CS_GCMP128 0x00000080 63 | #define CS_GCMP256 0x00000100 64 | #define CS_CCMP256 0x00000200 65 | #define CS_BIPGMAC128 0x00000400 66 | #define CS_BIPGMAC256 0x00000800 67 | #define CS_BIPCMAC256 0x00001000 68 | #define CS_UNKNOWN 0x00008000 69 | #define AKM_8021X 0x00010000 70 | #define AKM_PSK 0x00020000 71 | #define AKM_FT8021X 0x00040000 72 | #define AKM_FTPSK 0x00080000 73 | #define AKM_8021XSHA256 0x00100000 74 | #define AKM_PSKSHA256 0x00200000 75 | #define AKM_TDLS 0x00400000 76 | #define AKM_SAESHA256 0x00800000 77 | #define AKM_FTSAESHA256 0x01000000 78 | #define AKM_APPKA 0x02000000 79 | #define AKM_80211XBEAPSHA256 0x04000000 80 | #define AKM_80211XBEAPSHA384 0x08000000 81 | #define AKM_FT802xSHA384 0x10000000 82 | #define AKM_UNKNOWN 0x80000000 83 | u32 rsnie; 84 | u32 wpaie; 85 | u32 wpsie; 86 | u16 frequency; 87 | u8 rssi; 88 | char *encmode; 89 | char country[2]; 90 | u8 essidlen; 91 | u8 essid[ESSID_MAX]; 92 | }apdata_t; 93 | #define APDATA_SIZE (sizeof(apdata_t)) 94 | /*---------------------------------------------------------------------------*/ 95 | typedef struct __attribute__((__packed__)) 96 | { 97 | time_t tsakt; 98 | u8 maca[ETH_ALEN]; 99 | apdata_t *apdata; 100 | }aplist_t; 101 | #define APLIST_SIZE (sizeof(aplist_t)) 102 | /*---------------------------------------------------------------------------*/ 103 | static int sort_aplist_by_tsakt(const void *a, const void *b) 104 | { 105 | const aplist_t *ai = (const aplist_t *)a; 106 | const aplist_t *bi = (const aplist_t *)b; 107 | 108 | if(ai->tsakt < bi->tsakt) return 1; 109 | else if(ai->tsakt > bi->tsakt) return -1; 110 | return 0; 111 | } 112 | /*---------------------------------------------------------------------------*/ 113 | -------------------------------------------------------------------------------- /include/ieee80211.h: -------------------------------------------------------------------------------- 1 | /*===========================================================================*/ 2 | #define MAC_SIZE_ACK (10) 3 | #define MAC_SIZE_RTS (16) 4 | #define MAC_SIZE_NORM (24) 5 | #define MAC_SIZE_QOS (26) 6 | #define MAC_SIZE_LONG (30) 7 | #define MAC_SIZE_QOS_LONG (32) 8 | 9 | #define FCS_LEN 4 10 | 11 | /* types */ 12 | #define IEEE80211_FTYPE_MGMT 0x0 13 | #define IEEE80211_FTYPE_CTL 0x1 14 | #define IEEE80211_FTYPE_DATA 0x2 15 | #define IEEE80211_FTYPE_RCVD 0x3 16 | 17 | /* management */ 18 | #define IEEE80211_STYPE_ASSOC_REQ 0x0 19 | #define IEEE80211_STYPE_ASSOC_RESP 0x1 20 | #define IEEE80211_STYPE_REASSOC_REQ 0x2 21 | #define IEEE80211_STYPE_REASSOC_RESP 0x3 22 | #define IEEE80211_STYPE_PROBE_REQ 0x4 23 | #define IEEE80211_STYPE_PROBE_RESP 0x5 24 | #define IEEE80211_STYPE_BEACON 0x8 25 | #define IEEE80211_STYPE_ATIM 0x9 26 | #define IEEE80211_STYPE_DISASSOC 0xa 27 | #define IEEE80211_STYPE_AUTH 0xb 28 | #define IEEE80211_STYPE_DEAUTH 0xc 29 | #define IEEE80211_STYPE_ACTION 0xd 30 | #define IEEE80211_STYPE_NO_ACTION 0xe 31 | #define IEEE80211_STYPE_MGTRESERVED 0xf 32 | 33 | /* control */ 34 | #define IEEE80211_STYPE_TRIGGER 0x2 35 | #define IEEE80211_STYPE_VHT 0x5 36 | #define IEEE80211_STYPE_CTL_EXT 0x6 37 | #define IEEE80211_STYPE_BACK_REQ 0x8 38 | #define IEEE80211_STYPE_BACK 0x9 39 | #define IEEE80211_STYPE_PSPOLL 0xa 40 | #define IEEE80211_STYPE_RTS 0xb 41 | #define IEEE80211_STYPE_CTS 0xc 42 | #define IEEE80211_STYPE_ACK 0xd 43 | #define IEEE80211_STYPE_CFEND 0xe 44 | #define IEEE80211_STYPE_CFENDACK 0xf 45 | 46 | /* data */ 47 | #define IEEE80211_STYPE_DATA 0x0 48 | #define IEEE80211_STYPE_DATA_CFACK 0x1 49 | #define IEEE80211_STYPE_DATA_CFPOLL 0x2 50 | #define IEEE80211_STYPE_DATA_CFACKPOLL 0x3 51 | #define IEEE80211_STYPE_NULLFUNC 0x4 52 | #define IEEE80211_STYPE_CFACK 0x5 53 | #define IEEE80211_STYPE_CFPOLL 0x6 54 | #define IEEE80211_STYPE_CFACKPOLL 0x7 55 | #define IEEE80211_STYPE_QOS_DATA 0x8 56 | #define IEEE80211_STYPE_QOS_DATA_CFACK 0x9 57 | #define IEEE80211_STYPE_QOS_DATA_CFPOLL 0xa 58 | #define IEEE80211_STYPE_QOS_DATA_CFACKPOLL 0xb 59 | #define IEEE80211_STYPE_QOS_NULLFUNC 0xc 60 | #define IEEE80211_STYPE_QOS_CFACK 0xd 61 | #define IEEE80211_STYPE_QOS_CFPOLL 0xe 62 | #define IEEE80211_STYPE_QOS_CFACKPOLL 0xf 63 | 64 | /* Reason codes (IEEE 802.11-2007, 7.3.1.7, Table 7-22) */ 65 | #define WLAN_REASON_UNSPECIFIED 1 /* ok */ 66 | #define WLAN_REASON_PREV_AUTH_NOT_VALID 2 67 | #define WLAN_REASON_DEAUTH_LEAVING 3 68 | #define WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY 4 69 | #define WLAN_REASON_DISASSOC_AP_BUSY 5 70 | #define WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA 6 /* ok */ 71 | #define WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA 7 /* ok */ 72 | #define WLAN_REASON_DISASSOC_STA_HAS_LEFT 8 73 | #define WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH 9 74 | /* IEEE 802.11h */ 75 | #define WLAN_REASON_PWR_CAPABILITY_NOT_VALID 10 76 | #define WLAN_REASON_SUPPORTED_CHANNEL_NOT_VALID 11 77 | /* IEEE 802.11i */ 78 | #define WLAN_REASON_INVALID_IE 13 79 | #define WLAN_REASON_MICHAEL_MIC_FAILURE 14 80 | #define WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT 15 81 | #define WLAN_REASON_GROUP_KEY_UPDATE_TIMEOUT 16 82 | #define WLAN_REASON_IE_IN_4WAY_DIFFERS 17 83 | #define WLAN_REASON_GROUP_CIPHER_NOT_VALID 18 84 | #define WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID 19 85 | #define WLAN_REASON_AKMP_NOT_VALID 20 86 | #define WLAN_REASON_UNSUPPORTED_RSN_IE_VERSION 21 87 | #define WLAN_REASON_INVALID_RSN_IE_CAPAB 22 88 | #define WLAN_REASON_IEEE_802_1X_AUTH_FAILED 23 89 | #define WLAN_REASON_CIPHER_SUITE_REJECTED 24 90 | 91 | #define IEEE80211_SEQ_SEQ_MASK 0xfff0 92 | #define IEEE80211_SEQ_SEQ_SHIFT 4 93 | 94 | #define WBIT(n) (1 << (n)) 95 | #define WPA_KEY_INFO_TYPE_MASK (WBIT(0) | WBIT(1) | WBIT(2)) 96 | #define WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 WBIT(0) 97 | #define WPA_KEY_INFO_TYPE_HMAC_SHA1_AES WBIT(1) 98 | #define WPA_KEY_INFO_KEY_TYPE WBIT(3) /* 1 = Pairwise, 0 = Group key */ 99 | #define WPA_KEY_INFO_KEY_INDEX_MASK (WBIT(4) | WBIT(5)) 100 | #define WPA_KEY_INFO_KEY_INDEX_SHIFT 4 101 | #define WPA_KEY_INFO_INSTALL WBIT(6) /* pairwise */ 102 | #define WPA_KEY_INFO_TXRX WBIT(6) /* group */ 103 | #define WPA_KEY_INFO_ACK WBIT(7) 104 | #define WPA_KEY_INFO_MIC WBIT(8) 105 | #define WPA_KEY_INFO_SECURE WBIT(9) 106 | #define WPA_KEY_INFO_ERROR WBIT(10) 107 | #define WPA_KEY_INFO_REQUEST WBIT(11) 108 | #define WPA_KEY_INFO_ENCR_KEY_DATA WBIT(12) /* IEEE 802.11i/RSN only */ 109 | /*---------------------------------------------------------------------------*/ 110 | typedef struct __attribute__((packed)) 111 | { 112 | u64 timestamp; 113 | #if __BYTE_ORDER == __LITTLE_ENDIAN 114 | #define HCXTXBEACONINTERVAL 0x0400U 115 | #define HCXTXCAPABILITY 0x1431U 116 | #elif __BYTE_ORDER == __BIG_ENDIAN 117 | #define HCXTXBEACONINTERVAL 0x0004U 118 | #define HCXTXCAPABILITY 0x3114U 119 | #endif 120 | u16 beacon_interval; 121 | #define WLAN_CAPABILITY_PRIVACY (1<<4) 122 | u16 capability; 123 | u8 ie[1]; 124 | }ieee80211_beacon_proberesponse_t; 125 | #define IEEE80211_BEACON_SIZE offsetof(ieee80211_beacon_proberesponse_t, ie) 126 | #define IEEE80211_PROBERESPONSE_SIZE offsetof(ieee80211_beacon_proberesponse_t, ie) 127 | /*---------------------------------------------------------------------------*/ 128 | typedef struct __attribute__((packed)) 129 | { 130 | u8 ie[1]; 131 | }ieee80211_proberequest_t; 132 | #define IEEE80211_PROBEREQUEST_SIZE offsetof(ieee80211_proberequest_t, ie) 133 | /*===========================================================================*/ 134 | typedef struct __attribute__((__packed__)) 135 | { 136 | u8 category; 137 | #define RADIO_MEASUREMENT 5 138 | u8 code; 139 | #define NEIGHBOR_REPORT_REQUEST 4 140 | u8 dialog; 141 | u8 ie[1]; 142 | }ieee80211_action_t; 143 | #define IEEE80211_ACTION_SIZE offsetof(ieee80211_action_t, ie) 144 | /*---------------------------------------------------------------------------*/ 145 | typedef struct __attribute__((__packed__)) 146 | { 147 | #define OPEN_SYSTEM 0 148 | #define AUTHSUCCESS 0 149 | u16 algorithm; 150 | u16 sequence; 151 | u16 status; 152 | u8 ie[1]; 153 | }ieee80211_auth_t; 154 | #define IEEE80211_AUTH_SIZE offsetof(ieee80211_auth_t, ie) 155 | /*---------------------------------------------------------------------------*/ 156 | typedef struct __attribute__((__packed__)) 157 | { 158 | u16 capability; 159 | u16 status; 160 | #if __BYTE_ORDER == __LITTLE_ENDIAN 161 | #define HCXTXAID 0xc001U 162 | #elif __BYTE_ORDER == __BIG_ENDIAN 163 | #define HCXTXAID 0x01c0U 164 | #endif 165 | u16 aid; 166 | u8 ie[1]; 167 | }ieee80211_assoc_or_reassoc_resp_t; 168 | #define IEEE80211_ASSOCIATIONRESPONSE_SIZE offsetof(ieee80211_assoc_or_reassoc_resp_t, ie) 169 | #define IEEE80211_REASSOCIATIONRESPONSE_SIZE offsetof(ieee80211_assoc_or_reassoc_resp_t, ie) 170 | /*---------------------------------------------------------------------------*/ 171 | typedef struct __attribute__((__packed__)) 172 | { 173 | u16 capability; 174 | u16 listen_interval; 175 | u8 ie[1]; 176 | }ieee80211_assoc_req_t; 177 | #define IEEE80211_ASSOCIATIONREQUEST_SIZE offsetof(ieee80211_assoc_req_t, ie) 178 | /*---------------------------------------------------------------------------*/ 179 | typedef struct __attribute__((__packed__)) 180 | { 181 | u16 capability; 182 | u16 listen_interval; 183 | u8 current_macap[ETH_ALEN]; 184 | u8 ie[1]; 185 | }ieee80211_reassoc_req_t; 186 | #define IEEE80211_REASSOCIATIONREQUEST_SIZE offsetof(ieee80211_reassoc_req_t, ie) 187 | /*---------------------------------------------------------------------------*/ 188 | typedef struct __attribute__((__packed__)) 189 | { 190 | u8 id; 191 | #define TAG_SSID 0x00 192 | #define TAG_RATE 0x01 193 | #define TAG_CHAN 0x03 194 | #define TAG_COUNTRY 0x07 195 | #define TAG_RSN 0x30 196 | #define TAG_PAG 0xde 197 | #define TAG_VENDOR 0xdd 198 | u8 len; 199 | u8 ie[1]; 200 | #define RSNLEN_MIN 18 201 | #define WPALEN_MIN 22 202 | 203 | }ieee80211_ietag_t; 204 | #define IEEE80211_IETAG_SIZE offsetof(ieee80211_ietag_t, ie) 205 | 206 | /*---------------------------------------------------------------------------*/ 207 | typedef struct __attribute__((__packed__)) 208 | { 209 | u16 id; 210 | #define TAG_SSID 0x00 211 | u16 len; 212 | u8 et[1]; 213 | }ieee80211_ieet_t; 214 | #define IEEE80211_IEET_SIZE offsetof(ieee80211_ieet_t, ie) 215 | 216 | /*---------------------------------------------------------------------------*/ 217 | typedef struct __attribute__((__packed__)) 218 | { 219 | u8 control; 220 | u8 flags; 221 | }ieee80211_qos_t; 222 | #define IEEE80211_QOS_SIZE (sizeof(ieee80211_qos_t)) 223 | /*---------------------------------------------------------------------------*/ 224 | typedef struct __attribute__((__packed__)) 225 | { 226 | u8 dsap; 227 | u8 ssap; 228 | u8 control; 229 | u8 org[3]; 230 | u16 type; 231 | #define LLC_TYPE_AUTH 0x888e 232 | #define LLC_TYPE_IPV4 0x0800 233 | #define LLC_TYPE_IPV6 0x86dd 234 | #define LLC_TYPE_PREAUT 0x88c7 235 | #define LLC_TYPE_FRRR 0x890d 236 | }ieee80211_llc_t; 237 | #define IEEE80211_LLC_SIZE (sizeof(ieee80211_llc_t)) 238 | #define IEEE80211_LLC_SNAP 0xaa 239 | /*---------------------------------------------------------------------------*/ 240 | typedef struct __attribute__((__packed__)) 241 | { 242 | u8 version; 243 | u8 type; 244 | #define EAP_PACKET 0 245 | #define EAPOL_START 1 246 | #define EAPOL_LOGOFF 2 247 | #define EAPOL_KEY 3 248 | #define EAPOL_ASF 4 249 | #define EAPOL_MKA 5 250 | u16 len; 251 | u8 data[1]; 252 | }ieee80211_eapauth_t; 253 | #define IEEE80211_EAPAUTH_SIZE offsetof(ieee80211_eapauth_t, data) 254 | /*---------------------------------------------------------------------------*/ 255 | #define M1 1 256 | #define M2 2 257 | #define M3 3 258 | #define M4 4 259 | typedef struct __attribute__((__packed__)) 260 | { 261 | u8 keydescriptor; 262 | u16 keyinfo; 263 | u16 keylen; 264 | u64 replaycount; 265 | u8 nonce[32]; 266 | u8 keyiv[16]; 267 | u64 keyrsc; 268 | u8 keyid[8]; 269 | #define KEYMIC_MAX 16 270 | u8 keymic[KEYMIC_MAX]; 271 | u16 wpadatalen; 272 | u8 data[1]; 273 | }ieee80211_wpakey_t; 274 | #define IEEE80211_WPAKEY_SIZE offsetof(ieee80211_wpakey_t, data) 275 | /*---------------------------------------------------------------------------*/ 276 | typedef struct __attribute__((__packed__)) 277 | { 278 | u8 tag; 279 | u8 len; 280 | u8 pmkoui[4]; 281 | #define PMKID_MAX 16 282 | u8 pmkid[PMKID_MAX]; 283 | }ieee80211_pmkid_t; 284 | #define IEEE80211_PMKID_SIZE (sizeof(ieee80211_pmkid_t)) 285 | #define IEEE80211_PMKIDIE_SIZE (IEEE80211_PMKID_SIZE + IEEE80211_IETAG_SIZE) 286 | /*---------------------------------------------------------------------------*/ 287 | typedef struct __attribute__((__packed__)) 288 | { 289 | u16 count; 290 | u8 suite[4]; 291 | }ieee80211_suite_t; 292 | #define IEEE80211_SUITE_SIZE sizeof(ieee80211_suite_t) 293 | /*---------------------------------------------------------------------------*/ 294 | typedef struct __attribute__((__packed__)) 295 | { 296 | #define MFP_REQUIRED 0x40 297 | u16 capability; 298 | }ieee80211_rsncapability_t; 299 | #define IEEE80211_RSNCAPABILITY_SIZE sizeof(ieee80211_rsncapability_t) 300 | /*===========================================================================*/ 301 | /* DS bit usage 302 | * 303 | * TA = transmitter address 304 | * RA = receiver address 305 | * DA = destination address 306 | * SA = source address 307 | * 308 | * ToDS FromDS A1(RA) A2(TA) A3 A4 Use 309 | * ----------------------------------------------------------------- 310 | * 0 0 DA SA BSSID - IBSS/DLS 311 | * 0 1 DA BSSID SA - AP -> STA 312 | * 1 0 BSSID SA DA - AP <- STA 313 | * 1 1 RA TA DA SA unspecified (WDS) 314 | */ 315 | 316 | typedef struct __attribute__((__packed__)) 317 | { 318 | #if __BYTE_ORDER == __LITTLE_ENDIAN 319 | unsigned version : 2; 320 | unsigned type : 2; 321 | unsigned subtype : 4; 322 | 323 | unsigned to_ds : 1; 324 | unsigned from_ds : 1; 325 | unsigned more_frag : 1; 326 | unsigned retry : 1; 327 | unsigned power : 1; 328 | unsigned more_data : 1; 329 | unsigned prot : 1; 330 | unsigned ordered : 1; 331 | #define HCXTXDURATION 0x013aU 332 | #elif __BYTE_ORDER == __BIG_ENDIAN 333 | unsigned subtype : 4; 334 | unsigned type : 2; 335 | unsigned version : 2; 336 | 337 | unsigned ordered : 1; 338 | unsigned prot : 1; 339 | unsigned more_data : 1; 340 | unsigned power : 1; 341 | unsigned retry : 1; 342 | unsigned more_frag : 1; 343 | unsigned from_ds : 1; 344 | unsigned to_ds : 1; 345 | #define HCXTXDURATION 0x3a01U 346 | #endif 347 | u16 duration; 348 | u8 addr1[6]; 349 | u8 addr2[6]; 350 | u8 addr3[6]; 351 | u16 sequence; 352 | u8 addr4[6]; 353 | ieee80211_qos_t qos; 354 | }ieee80211_mac_t; 355 | /*===========================================================================*/ 356 | static const u8 zeroed[] = 357 | { 358 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 359 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 360 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 361 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 362 | }; 363 | 364 | static u8 macbc[] = 365 | { 366 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff 367 | }; 368 | 369 | #define WPAPSK 1 370 | #define RSNPSK 2 371 | #define RSNPSKFT 3 372 | #define RSNPSK256 4 373 | 374 | #define AKMPSK 2 375 | #define AKMPSKFT 4 376 | #define AKMPSK256 6 377 | 378 | #define SUITE_SIZE 4 379 | static const u8 rsnpmkid[SUITE_SIZE] = 380 | { 381 | 0x00, 0x0f, 0xac, 0x04 382 | }; 383 | static const u8 rsntkip[SUITE_SIZE] = 384 | { 385 | 0x00, 0x0f, 0xac, 0x02 386 | }; 387 | static const u8 rsnccmp[SUITE_SIZE] = 388 | { 389 | 0x00, 0x0f, 0xac, 0x04 390 | }; 391 | static const u8 rsnpsk[SUITE_SIZE] = 392 | { 393 | 0x00, 0x0f, 0xac, 0x02 394 | }; 395 | static const u8 rsnpskft[SUITE_SIZE] = 396 | { 397 | 0x00, 0x0f, 0xac, 0x04 398 | }; 399 | static const u8 rsnpsk256[SUITE_SIZE] = 400 | { 401 | 0x00, 0x0f, 0xac, 0x06 402 | }; 403 | static const u8 wpatype[SUITE_SIZE] = 404 | { 405 | 0x00, 0x50, 0xf2, 0x01 406 | }; 407 | static const u8 wpatkip[SUITE_SIZE] = 408 | { 409 | 0x00, 0x50, 0xf2, 0x02 410 | }; 411 | static const u8 wpaccmp[SUITE_SIZE] = 412 | { 413 | 0x00, 0x50, 0xf2, 0x04 414 | }; 415 | static const u8 wpapsk[SUITE_SIZE] = 416 | { 417 | 0x00, 0x50, 0xf2, 0x02 418 | }; 419 | static const u8 wpstype[SUITE_SIZE] = 420 | { 421 | 0x00, 0x50, 0xf2, 0x04 422 | }; 423 | 424 | static const int vendoraprg[] = 425 | { 426 | 0x00006C, 0x000101, 0x000578, 0x000B18, 0x000BF4, 0x000C53, 0x000D58, 0x000DA7, 427 | 0x000DC2, 0x000DF2, 0x000E17, 0x000E22, 0x000E2A, 0x000EEF, 0x000F09, 0x0016B4, 428 | 0x001761, 0x001825, 0x002067, 0x00221C, 0x0022F1, 0x00234A, 0x00238C, 0x0023F7, 429 | 0x002419, 0x0024FB, 0x00259D, 0x00269F, 0x005047, 0x005079, 0x0050C7, 0x0086A0, 430 | 0x00A054, 0x00A085, 0x00CB00, 0x0418B6, 0x0C8112, 0x100000, 0x105F02, 0x10B713, 431 | 0x1100AA, 0x111111, 0x146E0A, 0x18421D, 0x1CF4CA, 0x205B2A, 0x20D160, 0x24336C, 432 | 0x24FDFA, 0x3CB87A, 0x48062B, 0x487604, 0x48D35D, 0x48F317, 0x4CE136, 0x50E14A, 433 | 0x544E45, 0x580943, 0x586ED6, 0x6074F4, 0x609620, 0x60FCF1, 0x68E166, 0x706F81, 434 | 0x780B8C, 0x78F944, 0x7CE4AA, 0x806D97, 0x8C0734, 0x8C8401, 0x906F18, 0x90B4DD, 435 | 0x980EE4, 0x9C93E4, 0xA06260, 0xA4A6A9, 0xACDE48, 0xB025AA, 0xB0ECE1, 0xB0FEBD, 436 | 0xB4E1EB, 0xC8AACC, 0xD85DFB, 0xDC7014, 0xE4F14C, 0xE80410, 0xF03F03, 0xF49DA7 437 | }; 438 | #define VENDORAPRG_SIZE sizeof(vendoraprg) 439 | 440 | static const int vendorclientrg[] = 441 | { 442 | 0x780B8C, 0x78F944, 0x7CE4AA, 0x806D97, 0x8C0734, 0x8C8401, 0x906F18, 0x90B4DD, 443 | 0x980EE4, 0x9C93E4, 0xA06260, 0xA4A6A9, 0xACDE48, 0xB025AA, 0xB0ECE1, 0xB0FEBD, 444 | 0xB4E1EB, 0xC8AACC, 0xD85DFB, 0xDC7014, 0xE4F14C, 0xE80410, 0xF03F03, 0xF49DA7 445 | }; 446 | #define VENDORCLIENTRG_SIZE sizeof(vendorclientrg) 447 | /*===========================================================================*/ 448 | 449 | -------------------------------------------------------------------------------- /include/pcapng.h: -------------------------------------------------------------------------------- 1 | /*===========================================================================*/ 2 | #define PCAPMAGICNUMBER 0xa1b2c3d4 3 | #define PCAPMAGICNUMBERBE 0xd4c3b2a1 4 | 5 | #define PCAPNGBLOCKTYPE 0x0a0d0d0a 6 | #define PCAPNGMAGICNUMBER 0x1a2b3c4d 7 | #define PCAPNGMAGICNUMBERBE 0x4d3c2b1a 8 | 9 | #define PCAPNG_MAJOR_VER 1 10 | #define PCAPNG_MINOR_VER 0 11 | #define PCAPNG_BLOCK_SIZE 2048 12 | 13 | #define SHB_SYSINFO_LEN 256 14 | /*===========================================================================*/ 15 | /* Header of all pcapng options */ 16 | typedef struct __attribute__((__packed__)) 17 | { 18 | #define SHB_EOC 0 19 | #define SHB_COMMENT 1 20 | #define SHB_HARDWARE 2 21 | #define SHB_OS 3 22 | #define SHB_USER_APPL 4 23 | #define SHB_CUSTOM_OPT 0x0bad 24 | 25 | #define IF_NAME 2 26 | #define IF_DESCRIPTION 3 27 | #define IF_MACADDR 6 28 | #define IF_TSRESOL 9 29 | #define IF_TZONE 10 30 | 31 | #define TSRESOL_USEC 6 32 | #define TSRESOL_NSEC 9 33 | 34 | /* custom option code */ 35 | #define OPTIONCODE_MACORIG 0xf29a 36 | #define OPTIONCODE_MACAP 0xf29b 37 | #define OPTIONCODE_RC 0xf29c 38 | #define OPTIONCODE_ANONCE 0xf29d 39 | #define OPTIONCODE_MACCLIENT 0xf29e 40 | #define OPTIONCODE_SNONCE 0xf29f 41 | #define OPTIONCODE_WEAKCANDIDATE 0xf2a0 42 | #define OPTIONCODE_NMEA 0xf2a1 43 | 44 | u16 option_code; /* option code - depending of block (0 - end of opts, 1 - comment are in common) */ 45 | u16 option_length; /* option length - length of option in bytes (will be padded to 32bit) */ 46 | char option_data[1]; 47 | }option_header_t; 48 | #define OH_SIZE offsetof(option_header_t, option_data) 49 | /*===========================================================================*/ 50 | /* Option Field */ 51 | typedef struct __attribute__((__packed__)) 52 | { 53 | u16 option_code; 54 | u16 option_length; 55 | u64 option_value; 56 | }optionfield64_t; 57 | #define OPTIONFIELD64_SIZE (sizeof(optionfield64_t)) 58 | /*===========================================================================*/ 59 | /* total length*/ 60 | typedef struct __attribute__((__packed__)) 61 | { 62 | u32 total_length; 63 | }total_length_t; 64 | #define TOTAL_SIZE (sizeof(total_length_t)) 65 | /*===========================================================================*/ 66 | /* Section Header Block (SHB) - ID 0x0A0D0D0A */ 67 | typedef struct __attribute__((__packed__)) 68 | { 69 | u32 block_type; /* block type */ 70 | u32 total_length; /* block length */ 71 | u32 byte_order_magic; /* byte order magic - indicates swapped data */ 72 | u16 major_version; /* major version of pcapng (1 atm) */ 73 | u16 minor_version; /* minor version of pcapng (0 atm) */ 74 | s64 section_length; /* length of section - can be -1 (parsing necessary) */ 75 | }section_header_block_t; 76 | #define SHB_SIZE (sizeof(section_header_block_t)) 77 | /*---------------------------------------------------------------------------*/ 78 | /* Interface Description Block (IDB) - ID 0x00000001 */ 79 | typedef struct __attribute__((__packed__)) 80 | { 81 | u32 block_type; /* block type */ 82 | #define IDBID 0x00000001 83 | u32 total_length; /* block length */ 84 | u16 linktype; /* the link layer type (was -network- in classic pcap global header) */ 85 | u16 reserved; /* 2 bytes of reserved data */ 86 | u32 snaplen; /* maximum number of bytes dumped from each packet (was -snaplen- in classic pcap global header */ 87 | }interface_description_block_t; 88 | #define IDB_SIZE (sizeof(interface_description_block_t)) 89 | /*---------------------------------------------------------------------------*/ 90 | /* Custom Block (CB) - ID 0x00000bad */ 91 | typedef struct __attribute__((__packed__)) 92 | { 93 | u32 block_type; /* block type */ 94 | #define CBID 0x00000bad 95 | u32 total_length; /* block length */ 96 | u8 pen[4]; /* Private Enterprise Number */ 97 | u8 hcxm[32]; /* hcxdumptool magic number */ 98 | u8 data[1]; 99 | }custom_block_t; 100 | #define CB_SIZE offsetof (custom_block_t, data) 101 | /*---------------------------------------------------------------------------*/ 102 | /* Enhanced Packet Block (EPB) - ID 0x00000006 */ 103 | typedef struct __attribute__((__packed__)) 104 | { 105 | #define EPBID 0x00000006 106 | u32 block_type; /* block type */ 107 | u32 total_length; /* block length */ 108 | u32 interface_id; /* the interface the packet was captured from - identified by interface description block in current section */ 109 | u32 timestamp_high; /* high bytes of timestamp */ 110 | u32 timestamp_low; /* low bytes of timestamp */ 111 | u32 cap_len; /* length of packet in the capture file (was -incl_len- in classic pcap packet header) */ 112 | u32 org_len; /* length of packet when transmitted (was -orig_len- in classic pcap packet header) */ 113 | }enhanced_packet_block_t; 114 | #define EPB_SIZE (sizeof(enhanced_packet_block_t)) 115 | /*===========================================================================*/ 116 | static const u8 hcxmagic[] = 117 | { 118 | 0x2a, 0xce, 0x46, 0xa1, 0x79, 0xa0, 0x72, 0x33, 0x83, 0x37, 0x27, 0xab, 0x59, 0x33, 0xb3, 0x62, 119 | 0x45, 0x37, 0x11, 0x47, 0xa7, 0xcf, 0x32, 0x7f, 0x8d, 0x69, 0x80, 0xc0, 0x89, 0x5e, 0x5e, 0x98 120 | }; 121 | #define HCXMAGIC_SIZE (sizeof(hcxmagic)) 122 | /*===========================================================================*/ 123 | -------------------------------------------------------------------------------- /include/radiotap.h: -------------------------------------------------------------------------------- 1 | /*===========================================================================*/ 2 | #ifndef DLT_IEEE802_11_RADIO 3 | #define DLT_IEEE802_11_RADIO 127 4 | #endif 5 | /*===========================================================================*/ 6 | #define IEEE80211_RADIOTAP_TSFT 0x00000001 7 | #define IEEE80211_RADIOTAP_FLAGS 0x00000002 8 | #define IEEE80211_RADIOTAP_RATE 0x00000004 9 | #define IEEE80211_RADIOTAP_CHANNEL 0x00000008 10 | #define IEEE80211_RADIOTAP_FHSS 0x00000010 11 | #define IEEE80211_RADIOTAP_DBM_ANTSIGNAL 0x00000020 12 | #define IEEE80211_RADIOTAP_DBM_ANTNOISE 0x00000040 13 | #define IEEE80211_RADIOTAP_LOCK_QUALITY 0x00000080 14 | #define IEEE80211_RADIOTAP_TX_ATTENUATION 0x00000100 15 | #define IEEE80211_RADIOTAP_DB_TX_ATTENUATION 0x00000200 16 | #define IEEE80211_RADIOTAP_DBM_TX_POWER 0x00000400 17 | #define IEEE80211_RADIOTAP_ANTENNA 0x00000800 18 | #define IEEE80211_RADIOTAP_DB_ANTSIGNAL 0x00001000 19 | #define IEEE80211_RADIOTAP_DB_ANTNOISE 0x00002000 20 | #define IEEE80211_RADIOTAP_RX_FLAGS 0x00004000 21 | #define IEEE80211_RADIOTAP_TX_FLAGS 0x00008000 22 | #define IEEE80211_RADIOTAP_RTS_RETRIES 0x00010000 23 | #define IEEE80211_RADIOTAP_DATA_RETRIES 0x00020000 24 | /* 18 is XChannel, not defined */ 25 | #define IEEE80211_RADIOTAP_MCS 0x00080000 26 | #define IEEE80211_RADIOTAP_AMPDU_STATUS 0x00100000 27 | #define IEEE80211_RADIOTAP_VHT 0x00200000 28 | #define IEEE80211_RADIOTAP_TIMESTAMP 0x00400000 29 | /* valid in every it_present bitmap, even vendor namespaces */ 30 | #define IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE 0x20000000 31 | #define IEEE80211_RADIOTAP_VENDOR_NAMESPACE 0x40000000 32 | #define IEEE80211_RADIOTAP_EXT 0x80000000 33 | /*---------------------------------------------------------------------------*/ 34 | #define IEEE80211_RADIOTAP_F_CFP 0x01 35 | #define IEEE80211_RADIOTAP_F_SHORTPRE 0x02 36 | #define IEEE80211_RADIOTAP_F_WEP 0x04 37 | #define IEEE80211_RADIOTAP_F_FRAG 0x08 38 | #define IEEE80211_RADIOTAP_F_FCS 0x10 39 | #define IEEE80211_RADIOTAP_F_DATAPAD 0x20 40 | #define IEEE80211_RADIOTAP_F_BADFCS 0x40 41 | /*===========================================================================*/ 42 | typedef struct __attribute__((__packed__)) 43 | { 44 | u8 it_version; 45 | u8 it_pad; 46 | u16 it_len; 47 | u32 it_present; 48 | }rth_t; 49 | #define RTHRX_SIZE (ssize_t)(sizeof(rth_t)) 50 | /*---------------------------------------------------------------------------*/ 51 | static const u8 rthtxdata[] = 52 | { 53 | 0x00, 0x00, /* radiotap version and padding */ 54 | 0x0c, 0x00, /* radiotap header length */ 55 | 0x06, 0x80, 0x00, 0x00, /* bitmap */ 56 | 0x00, /* all flags cleared */ 57 | 0x02, /* rate */ 58 | 0x18, 0x00 /* tx flags */ 59 | }; 60 | #define RTHTX_SIZE sizeof(rthtxdata) 61 | /*===========================================================================*/ 62 | -------------------------------------------------------------------------------- /include/raspberry.h: -------------------------------------------------------------------------------- 1 | /*===========================================================================*/ 2 | #define RPINAME_SIZE 12 3 | #define RASPBERRY_INFO 2048 4 | #define GPIO_LED_DELAY 100000000L 5 | 6 | #define RPI_BLOCK_SIZE (4*1024) 7 | 8 | #define INP_GPIO(g) *(gpio +((g) /10)) &= ~(7 << (((g) %10) *3)) 9 | #define OUT_GPIO(g) *(gpio +((g) /10)) |= (1 << (((g) %10) *3)) 10 | #define GPIO_SET *(gpio +7) 11 | #define GPIO_CLR *(gpio +10) 12 | #define GET_GPIO(g) (*(gpio +13) & (1 << g)) 13 | 14 | static void *gpio_map; 15 | static volatile unsigned *gpio; 16 | static const char rpiname[] = "Raspberry Pi"; 17 | /*===========================================================================*/ 18 | -------------------------------------------------------------------------------- /include/types.h: -------------------------------------------------------------------------------- 1 | /*===========================================================================*/ 2 | typedef uint8_t u8; 3 | typedef uint16_t u16; 4 | typedef uint32_t u32; 5 | typedef uint64_t u64; 6 | 7 | typedef int8_t s8; 8 | typedef int16_t s16; 9 | typedef int32_t s32; 10 | typedef int64_t s64; 11 | /*===========================================================================*/ 12 | -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2000-2025 ZeroBeat 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /man/hcxdumptool.1: -------------------------------------------------------------------------------- 1 | .\" Manpage for hcxdumptool. 2 | .\" Contact https://github.com/ZerBea to correct errors or typos. 3 | .TH man 1 "23 October 2021" "1.0" "hcxdumptool man page" 4 | .SH NAME 5 | hcxtools 6 | .SH DESCRIPTION 7 | Small tool to capture packets from wlan devices and to detect weak points within own WiFi networks. 8 | .SH TOOLS 9 | .nf 10 | | hcxdumptool | Tool to run several tests to determine if ACCESS POINTs or CLIENTs are vulnerable | 11 | .SH OPTIONS 12 | help menu (-h or --help) of each tool will list all available options 13 | .SH RELATED TOOLS 14 | hcxpcapngtool, hcxhashtool, hcxpsktool, hcxpmktool, hcxeiutool, hcxwltool, hcxhash2cap, whoismac, wlancap2wpasec, wlangenpmk, wlangenpmkocl 15 | .SH BUGS 16 | no known bugs. 17 | .SH AUTHOR 18 | ZeroBeat (https://github.com/ZerBea) 19 | -------------------------------------------------------------------------------- /usefulscripts/startnlmon: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo "Activating NETLINK monitor" 4 | sudo ip link add nlmon0 type nlmon 5 | sudo ip link set dev nlmon0 up 6 | -------------------------------------------------------------------------------- /usefulscripts/startnm: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo "Activating NetworkManager" 4 | sudo systemctl start NetworkManager.service 5 | sudo systemctl start wpa_supplicant.service 6 | -------------------------------------------------------------------------------- /usefulscripts/stopnm: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo "Deactivating NetworkManager" 4 | sudo systemctl stop NetworkManager.service 5 | sudo systemctl stop wpa_supplicant.service 6 | --------------------------------------------------------------------------------