Thursday, February 26, 2004

Adventures in Flashing Firmware

Yesterday I began a journey to get two of my 802.11b NICs to function as promiscuous sniffers. I own a SMC EZ Connect 802.11b Wireless PCMCIA card, model 2632W v.1, and a SMC EZ Connect 802.11b Wireless PCI card, model 2602W v.1. I wanted to use Tcpdump's new ieee802_11_radio options to see raw 802.11 traffic, announced for FreeBSD in December.

I started with the 2632W and had the most luck. It worked as a normal NIC under FreeBSD 5.2, but I could not get it to work with the bsd-airtools, even with the net-mgmt/bsd-airtools port. I had installed the net/libpcap and net/tcpdump ports.

This is how the 2632W looked to FreeBSD 5.2 REL:

orr:/root# dmesg | grep wi0
wi0: at port 0x100-0x13f irq 11 function 0 config 1 on pccard0
wi0: 802.11 address: 00:04:e2:29:3b:ba
wi0: using RF:PRISM2 MAC:HFA3841 CARD:HWB3163 rev.A
wi0: Intersil Firmware: Primary (0.3.0), Station (0.8.3)
wi0: 11b rates: 1Mbps 2Mbps 5.5Mbps 11Mbps

orr:/root# ifconfig wi0 up
orr:/root# ifconfig wi0
wi0: flags=8843 mtu 1500
inet6 fe80::204:e2ff:fe29:3bba%wi0 prefixlen 64 scopeid 0x5
ether 00:04:e2:29:3b:ba
media: IEEE 802.11 Wireless Ethernet autoselect (DS/11Mbps)
status: associated
ssid shaolin 1:shaolin
stationname "FreeBSD WaveLAN/IEEE node"
channel 6 authmode OPEN powersavemode OFF powersavesleep 100
wepmode OFF weptxkey 1

The NIC appeared to associate itself with my access point even though I did not tell it to. It did not know the WEP key in any case.

I tried using the new Tcpdump to see raw 802.11 traffic:

orr:/root# /usr/local/sbin/tcpdump -ne -X -s 1520 -i wi0 -y IEEE802_11
tcpdump: data link type IEEE802_11
tcpdump: WARNING: wi0: no IPv4 address assigned
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on wi0, link-type IEEE802_11 (802.11), capture size 1520 bytes
18:29:02.535912 BSSID:00:a0:c5:59:47:d4 SA:00:06:25:45:74:be DA:00:a0:c5:59:47:d
4 LLC, dsap 0xd5, ssap 0x09, cmd 0x00, sap 08 > sap d5 I (s=0,r=0,R) len=72
0x0000 d509 0000 4557 799a 078e b569 00f0 5b25 ....EWy....i..[%
0x0010 c5fa b52f 4e15 7299 d636 b8ab 6dfd cb66 .../N.r..6..m..f
0x0020 5fd0 3f74 c25e 0887 de76 1656 0161 e45a _.?t.^...v.V.a.Z
0x0030 00aa c748 1794 1ed2 e42b 94c9 6d21 a29e ...H.....+..m!..
0x0040 849b 239f 5233 750d 9459 d644 ..#.R3u..Y.D

That was something, but not what I expected. I tried putting the card into monitor mode based on a thread on freebsd-mobile.

orr:/root# ifconfig wi0 mediaopt monitor
orr:/root# ifconfig wi0
wi0: flags=8843 mtu 1500
inet6 fe80::204:e2ff:fe29:3bba%wi0 prefixlen 64 scopeid 0x5
ether 00:04:e2:29:3b:ba
media: IEEE 802.11 Wireless Ethernet autoselect (DS/2Mbps )
status: associated
ssid ""
stationname "FreeBSD WaveLAN/IEEE node"
channel 11 authmode OPEN powersavemode OFF powersavesleep 100
wepmode OFF weptxkey 1

orr:/root# /usr/local/sbin/tcpdump -ne -X -s 1520 -i wi0 -y IEEE802_11
tcpdump: data link type IEEE802_11
tcpdump: WARNING: wi0: no IPv4 address assigned
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on wi0, link-type IEEE802_11 (802.11), capture size 1520 bytes
...nothing...

I thought perhaps I needed to place the card in "promiscuous" mode, so I tried that next:

orr:/root# ifconfig wi0 promisc
orr:/root# ifconfig wi0
wi0: flags=28943 mtu 1500
inet6 fe80::204:e2ff:fe29:3bba%wi0 prefixlen 64 scopeid 0x5
ether 00:04:e2:29:3b:ba
media: IEEE 802.11 Wireless Ethernet autoselect (DS/2Mbps )
status: associated
ssid ""
stationname "FreeBSD WaveLAN/IEEE node"
channel 11 authmode OPEN powersavemode OFF powersavesleep 100
wepmode OFF weptxkey 1

Again, Tcpdump saw nothing. Now I realized I needed stronger magic. I visited Jun Sun's mini-HOWTO for flashing Intersil Prism firmware.

He mentioned using openap-ct, which offers a Linux floppy-based distro containing the Host AP driver and utilities. One of the utilities, prism2_srec, is built to flash NIC firmware. Using prism2_srec assumes one can use one of the hostap drivers, like hostap_cs. Looking at the hostap_cs.conf, I saw an entry for my NIC:

card "SMC 2632W 11Mbps WLAN Card"
version "SMC", "SMC2632W", "Version 01.02"
bind "hostap_cs"

Next I needed to find the firmware itself. Red-bean had the most comprehensive list. I downloaded several of the newer archives, unzipped them, and made them available on one of my Web servers. One nice aspect of prism2_srec is it will tell you which firmware files are compatible with your NIC before burning.

I created a floppy with the openap-ct image, booted my laptop with it, and then experimented with prism2_srec following Jun Sun's instructions. When I started the process this was the state of my NIC's firmware:

NIC: id=0x8002 v1.0.0
PRI: id=0x15 v0.3.0
STA: id=0x1f v0.8.3

I only needed to update the third category, station firmware. According to this readme, the primary firmware could stay at 0.3.0. I flashed the station firmware with the s1010701.hex image. When done my card looked like this:

NIC: id=0x8002 v1.0.0
PRI: id=0x15 v0.3.0
STA: id=0x1f v1.7.1

After a reboot back into FreeBSD, dmesg and ifconfig reported:

orr:/root# dmesg | grep wi0
wi0: at port 0x100-0x13f irq 11 function 0 config 1 on pccard1
wi0: 802.11 address: 00:04:e2:29:3b:ba
wi0: using RF:PRISM2 MAC:HFA3841 CARD:HWB3163 rev.A
wi0: Intersil Firmware: Primary (0.3.0), Station (1.7.1)
wi0: 11b rates: 1Mbps 2Mbps 5.5Mbps 11Mbps

orr:/root# ifconfig wi0
wi0: flags=8802 mtu 1500
ether 00:04:e2:29:3b:ba
media: IEEE 802.11 Wireless Ethernet autoselect (none)
ssid ""
stationname "FreeBSD WaveLAN/IEEE node"
channel -1 authmode OPEN powersavemode OFF powersavesleep 100
wepmode OFF weptxkey 1

I gave Tcpdump a try:

orr:/root# ifconfig wi0 mediaopt monitor channel 11 up
orr:/root# ifconfig wi0
wi0: flags=8843 mtu 1500
inet6 fe80::204:e2ff:fe29:3bba%wi0 prefixlen 64 scopeid 0x4
ether 00:04:e2:29:3b:ba
media: IEEE 802.11 Wireless Ethernet autoselect (DS/2Mbps )
status: associated
ssid ""
stationname "FreeBSD WaveLAN/IEEE node"
channel 11 authmode OPEN powersavemode OFF powersavesleep 100
wepmode OFF weptxkey 1

orr:/root# /usr/local/sbin/tcpdump -n -i wi0 -y IEEE802_11 -vv -s 1515 -X
tcpdump: data link type IEEE802_11
tcpdump: WARNING: wi0: no IPv4 address assigned
tcpdump: listening on wi0, link-type IEEE802_11 (802.11), capture size 1515 bytes
12:14:28.344865 0us Probe Request (shaolin) [1.0* 2.0* 5.5* 11.0* Mbit]
0x0000 0007 7368 616f 6c69 6e01 0482 848b 96 ..shaolin......
12:14:28.377546 0us Probe Request (shaolin) [1.0* 2.0* 5.5* 11.0* Mbit]
0x0000 0007 7368 616f 6c69 6e01 0482 848b 96 ..shaolin......

That was certainly better! I also tried the "radio" version:

orr:/var# /usr/local/sbin/tcpdump -n -i wi0 -y IEEE802_11_RADIO -vv -s 1515 -X
tcpdump: listening on wi0, link-type IEEE802_11_RADIO
(802.11 plus radio information header), capture size 1515 bytes
12:13:36.428377 [|802.11]
12:13:36.523975 [|802.11]
12:13:36.540299 [|802.11]

This was an improvement, but I wasn't seeing nearly everything I thought I would. I realized I was monitoring channel 11, not channel 6. In fact, everything seen thus far was bleeding into channel 11 from channel 6! I adjusted my channel and saw much more traffic:

orr:/root# ifconfig wi0 mediaopt monitor channel 6 up

orr:/root# /usr/local/sbin/tcpdump -n -i wi0 -y IEEE802_11_RADIO -vv -s 1515 -X
tcpdump: data link type IEEE802_11_RADIO
tcpdump: WARNING: wi0: no IPv4 address assigned
tcpdump: listening on wi0, link-type IEEE802_11_RADIO
(802.11 plus radio information header), capture size 1515 bytes
12:26:05.986183 [|802.11]
12:26:06.025324 [|802.11]
12:26:06.045314 [|802.11]
12:26:06.088574 [|802.11]
12:26:06.147281 [|802.11]

orr:/root# /usr/local/sbin/tcpdump -n -i wi0 -y IEEE802_11 -vv -s 1515 -X
tcpdump: data link type IEEE802_11
tcpdump: WARNING: wi0: no IPv4 address assigned
tcpdump: listening on wi0, link-type IEEE802_11 (802.11), capture size 1515 byte
s
12:26:25.851579 0us Beacon (LIMHOME) [1.0* 2.0* 5.5 11.0 Mbit] ESS CH: 6
0x0000 2571 61c2 d900 0000 6400 0500 0007 4c49 %qa.....d.....LI
0x0010 4d48 4f4d 4501 0482 840b 1603 0106 0406 MHOME...........
0x0020 0102 0000 0000 0504 0001 0000 ............
12:26:25.910662 0us Beacon (shaolin) [1.0* 2.0* 5.5* 11.0* Mbit] ESS CH: 6, PRIVACY
0x0000 2cc2 0ac7 7d04 0000 6400 1100 0007 7368 ,...}...d.....sh
0x0010 616f 6c69 6e01 0482 848b 9603 0106 0504 aolin...........
0x0020 0001 0000 ....
12:26:26.013037 0us Beacon (shaolin) [1.0* 2.0* 5.5* 11.0* Mbit] ESS CH: 6, PRIVACY
0x0000 1b52 0cc7 7d04 0000 6400 1100 0007 7368 .R..}...d.....sh
0x0010 616f 6c69 6e01 0482 848b 9603 0106 0504 aolin...........
0x0020 0001 0000 ....

Now that I could see all of this traffic, I tried some of the bsd-airtools. First I used prism2ctl to see the state of the NIC:

orr:/root# prism2ctl wi0
Sleep mode: [ Off ]
Suppress post back-off delay: [ Off ]
Suppress Tx Exception: [ Off ]
Monitor mode: [ Off ]
LED Test: [ ]
Continuous Tx: [ ]
Continuous Rx: [ Off ]
Signal State: [ ]
Automatic level control: [ Off ]

Prism2ctl reported the NIC was not in monitor mode, so I enabled it:

orr:/root# prism2ctl wi0 -m
orr:/root# prism2ctl wi0
Sleep mode: [ Off ]
Suppress post back-off delay: [ Off ]
Suppress Tx Exception: [ Off ]
Monitor mode: [ On ]
LED Test: [ ]
Continuous Tx: [ ]
Continuous Rx: [ Off ]
Signal State: [ ]
Automatic level control: [ Off ]

orr:/root# ifconfig wi0
wi0: flags=8843 mtu 1500
inet6 fe80::204:e2ff:fe29:3bba%wi0 prefixlen 64 scopeid 0x4
ether 00:04:e2:29:3b:ba
media: IEEE 802.11 Wireless Ethernet autoselect (DS/2Mbps )
status: associated
ssid ""
stationname "FreeBSD WaveLAN/IEEE node"
channel 6 authmode OPEN powersavemode OFF powersavesleep 100
wepmode OFF weptxkey 1

Next I tried prism2dump:

orr:/root# prism2dump wi0
prism2dump: listening on wi0
- [ff:ff:ff:ff:ff:ff <- 0:c:41:f6:6c:24 <- 0:c:41:f6:6c:24]
- port: 7 ts: 223.792288 1:5 10:0
- sn: 21872 (72:31:bf:e7:2d:35) len: 59
- ** mgmt-beacon ** ts: 833469.849995 int: 100 capinfo: ess
+ ssid: [linksys]
+ rates: 1.0 2.0 5.5 11.0 18.0 24.0 36.0 54.0
+ ds ch: 6
+ dtim c: 0 p: 1 bc: 0 pvb: bfbfea45

- [ff:ff:ff:ff:ff:ff <- 0:a0:c5:59:47:D4 <- 0:a0:c5:59:47:d4]
- port: 7 ts: 223.815868 0:38 110:0
- sn: 17952 (1f:cf:13:ad:ea:bb) len: 36
- ** mgmt-beacon ** ts: 4938366.259564 int: 100 capinfo: ess priv
+ ssid: [shaolin]
+ rates: 1.0 2.0 5.5 11.0
+ ds ch: 6
+ dtim c: 0 p: 1 bc: 0 pvb: bfbfea45

That worked as advertised. I also tried dwepdump and dwepcrack:

orr:/root# dwepdump wi0 /var/dwep.dump
* dwepdump v0.2 by h1kari *
* Copyright (c) Dachb0den Labs 2002 [http://dachb0den.com] *
starting pcap capture loop...
device: wi0
logfile: /var/dwep.dump
packets received: 1

orr:/root# dwepcrack /var/dwep.dump
usage: dwepcrack [-j ] [-b [-e] | -w [-f ]] [-s] [wordfile]
-j: number of processes to run (useful for smp systems)
-b: brute force key by exhausting all probable possibilities
-e: search the entire key width (will take a while)
-w: use weak ksa attack
-f: fudge the probability scope by specified count (might take a while)
-s: file uses 104-bit wep
orr:/root# dwepcrack -b /var/dwep.dump
* dwepcrack v0.5 by h1kari *
* Copyright (c) Dachb0den Labs 2003 [http://dachb0den.com] *
starting brute force crack on smallest packet:
packet length: 36
init vector: 01:53:6d
default tx key: 3
progress: ....................................................................

I even got dstumbler to work.

Next I turned to the SMC 2602W v.1 PCI NIC. This card destroyed me. I spent hours trying to get it to work. The problem is the card is literally a SMC 2632W v.1 PCMCIA card plugged into a PLX riser that sits in a PCI slot. First I tried the openap-ct solution, but the hostap_plx module did not like it. This ruled out using prism2_srec.

I tried to get fancy by using Knoppix. I found that the linux-wlan-ng prism2_plx driver recognized the card under Knoppix, but I couldn't use this to my advantage. The linux-wlan-ng project provides prism2dl to flash firmware, but I wasn't ready to install a whole new Linux distribution and include these drivers. I did waste some time using these Red Hat 9.0 kernel RPMs with hostap built-in on my Red Hat 9 box. They didn't help, and I found these RPMs too late.

Abandoning Linux, I turned to Windows. A visit to www.smc-europe.com revealed the same WinUpdate program Jun Sun mentioned on his page. Unfortunately my Optiplex GX100 box running Windows 2000 did not recognize the NIC. It complained it could not communicate with the driver. I tried flashing the Dell's BIOS to the latest version, but still no luck.

While moving the NIC between machines I must have unseated the RAM in the Dell Optiplex. It refused to boot but gave me a one beep - three beeps - two beeps error code. Checking Dell's Phoenix BIOS beep codes I learned 1-3-2 meant "RAM Refresh verification failure." All I thought to do was reseat the RAM, which fixed the problem.

I thought using a DOS-based flash method might be my last option. Intersil provided a utility called FLASH.EXE, which is available here, along with its .pdf manual and a flash.ini file. I gave this program a try but it could not find the NIC either. I decided to install a new copy of Windows 2000 on the newest tower PC I had, my Shuttle SB52G. After wasting time doing that, I gave the WinUpdate program a try. It acted flaky, also saying it couldn't contact the NIC (just as the newly installed SMC drivers complained -- what's wrong with SMC?), but, lo and behold, a miracle occurred. Somehow I was still able to flash the firmware. I brought the station firmware up to the same 1.7.1 version on the PCMCIA NIC. I thought my problems were solved!

Alas, under both FreeBSD 4.9 STABLE (on the hard drive) and FreeBSD 5.2 (under FreeSBIE), I got these messages:

Feb 26 13:06:37 bourque /kernel: wi0: port 0xc400-0xc43f,0xc
000-0xc07f mem 0xe8050000-0xe8050fff irq 5 at device 5.0 on pci1
Feb 26 13:06:37 bourque /kernel: wi0: 802.11 address: 00:04:e2:29:4c:3c
Feb 26 13:06:37 bourque /kernel: wi0: using RF:PRISM2 MAC:HFA3841 CARD:HWB3163 rev.A
Feb 26 13:06:37 bourque /kernel: wi0: Intersil Firmware: Primary 0.03.00, Station 1.07.01
Feb 26 13:06:37 bourque /kernel: wi0: time out allocating memory on card
Feb 26 13:06:37 bourque /kernel: wi0: tx buffer allocation failed
Feb 26 13:06:37 bourque /kernel: wi0: failed to allocate 1594 bytes on NIC
Feb 26 13:06:37 bourque /kernel: wi0: mgmt. buffer allocation failed
Feb 26 13:08:55 bourque /kernel: wi0: time out allocating memory on card
Feb 26 13:08:55 bourque /kernel: wi0: tx buffer allocation failed
Feb 26 13:08:55 bourque /kernel: wi0: failed to allocate 1594 bytes on NIC
Feb 26 13:08:55 bourque /kernel: wi0: mgmt. buffer allocation failed
...and so on...

Flashing the firmware made no difference. These errors are similar to those reported here and here.

I decided to abandon the SMC 2602W v.1 NIC and buy a Linksys WMP55AG A+G PCI NIC. FreeBSD's ath driver works with the Atheros chip. Once I get the NIC, I'll report my findings.