Monday, January 23, 2012

Android Kismet progress

Android process management sucks.  It's almost as if they don't want you to exec a native binary sanely (hint - they don't.)  This made it impossible to clean up a Kismet server process if a new apk was deployed, or the thread crashed, or whatever.

Ended up porting Kismet to run as a NDK shared library by adding a small wrapper that turns a jstring into an argc/argv[] pair and wraps main(), then runs the whole show in a java thread as a JNI call.

Tossed together a ridiculously basic Kismet client in java to get a display back on the main window; previously it scraped stdout from a kismet_server binary running via Runtime.exec.  All the client does right now is turn off *TIME and turn on *STATUS


Everything but the UI runs in a service which stays running in the background.  Because currently kismet runs in a sharedlib with effectively no mods (added an ifdef to not build tuntap), it isn't killable as a thread.  A future mod would be to add a jni call that clobbers globalreg->fatal-condition to cause a kismet shutdown.

Right now Kismet throws some spurious errors because it isn't configured  to have any writeable directories to store tags, etc.  I don't care right now.

Thanks to Laen and Dorkbot, got some USB power injector boards being made as well:

Super simple board to pull 5v from a battery pack, and prevent VCC from the phone from being connected to the radio.

Friday, January 20, 2012

Kismet on Android

So it's super unstable, but Kismet can run on android now:

Requires Android 4.x for USB host, does NOT require root.

Packets are captured with userspace rtl8187 driver written in java, sent to a kismet-drone work-alike also written in java, which allows an unmodified kismet_server to read them.

Output is kluged into a textview to at least be able to see what's going on.

Currently the code doesn't channel hop, though that should be possible without too much trouble.  The process.exec thread doesn't kill off kismet_server when the background service ends, there's usb init timing problems, etc, but it's a major step forwards.

Ultimately, kismet_server will be hidden completely and the Java UI will tap the kismet client protocol for a native display.

Still... progress!  Code and test apk to come in the future.

Monday, January 16, 2012

Capturing raw 802.11 on android

Short answer: It's not really possible, definitely not on an unrooted device, if you're using the built-in nic.  The drivers and firmware aren't monitor mode friendly, and you'd need to root the device (and give the app root) to be able to even attempt.

Giving android apps root terrifies me - it places 100% trust in the developer to not be malicious, and the market to have not presented you with a cloned project that IS malicious, and in the developers systems to make sure no-one can ever push an update using their keys that becomes malicious... it's bad news all around.

Fortunately, in Honeycomb and in ICS, they've added USB host mode.  Unfortunately, in honeycomb something seems to not be quite right with it (but honeycomb is a dead end anyhow, most devices with it should be seeing an ICS update very soon), and there's only one official ICS phone right now.

The android USB API is very similar to libusb.  It's possible to compile libusb on android in the NDK.  Unfortunately, claiming a device via the android USB api does NOT make the endpoints directly writeable to the app uid.  There is a method to shunt the USB file descriptor to a native segment, which may prove useful in the future.

Even without using native code, it's possible to bit-bang a USB device directly using the Android java API; a simple example is the Wi-Spy, which has a pleasantly simple hardware interface...

There's nothing innately special about a wifi device, in USB terms, other than general complexity.  Having crazy ideas sometimes, I took chunks of the Serialmonkey rtl8187 driver, the macusbwifi port of it to mac userspace, and the linux kernel driver for rtl8187, and mangled them into a 2500 line pure-java implementation of the driver, with IO shunted through the android USB API:

I/ActivityManager(  206): Start proc for activity pid=1965 uid=10072 gids={}
D/rtl8187card( 1965): device interface count: 1
D/rtl8187card( 1965): open SUCCESS
D/rtl8187card( 1965): hwaddr 0:c0:ca:21:9d:ef RTL8187BvB V1+RTL8225
E/rtl8187card( 1965): 8187z2 rf calibration failed: e6
D/rtl8187card( 1965): rtl8225z2 set tx power
D/rtl8187card( 1965): Initialized card hardware
D/rtl8187card( 1965): Started rtl8187
D/rtl8187card( 1965): Successfully calibrated & started hw
D/rtl8187card( 1965): Set channel 11
D/rtl8187card( 1965): Initializing URB request for max 512

I'm honestly not sure at the moment why the rf calibration code is getting a failure bit set, that will be a problem to look at in the future.

The result?

D/rtl8187card( 1965): Packetdata 2...
  Data 80 00 00 00 ff ff ff ff ff ff 00 24 6c a7 87 70     ...........$l..p
  Data 00 24 6c a7 87 70 b0 11 81 d1 fb 01 00 00 00 00     .$l..p..........
  Data 64 00 31 04 00 10 65 74 68 65 72 73 70 68 65 72     d.1...etherspher
  Data 65 2d 77 70 61 32 01 08 82 84 0b 16 0c 12 18 24     e-wpa2.........$
  Data 03 01 0b 05 04 00 01 00 00 2a 01 00 32 04 30 48     .........*..2.0H
  Data 60 6c 30 14 01 00 00 0f ac 04 01 00 00 0f ac 04     `l0.............
  Data 01 00 00 0f ac 01 00 00 dd 18 00 50 f2 02 01 01     ...........P....

The post mangles the formatting a little, but it's clearly a beacon packet (0x80), the SSID is visible, we're in good shape!

The code currently needs a lot of care and feeding before a release, though hopefully by Shmoocon I can show some basic results.

In theory there shouldn't be much trouble porting the Kismet core over to the phone and shunting the packets through the JNI interface to that, and letting the existing code to the decoding and logging, but I haven't started on that yet.

The battery drain on the phone is pretty significant - I'm kind of amazed it can handle it at all, considering some netbooks can't drive these Alfa nics.  A hard-drive power Y cable offsets it to some extent, someone suggested making a custom cable which severs VCC from the device and uses the aux connector exclusively, this seems like a pretty good idea to me.

Monday, January 9, 2012

Reaver / WPS Brute Force IDS

Thanks to Render and Dutch for pushing on this and contributing pcaps.

Kismet-SVN now detects a WPS brute force attack underway via tools such as Reaver.

Reaver exploits a weakness in WPS which reduces the potential keyspace to 11,000 PINs, exploitable in a matter of hours.

Kismet WPS brute-force detection alerts on an access point which is doing an unusual amount of WPS traffic, specifically by monitoring for the M3 exchange of the WPS handshake.  An access point should only perform a WPS exchange with new clients, excessive WPS communications indicate a likely attack.

The WPS detector is implemented in the newly minted phy-neutral tracking layer of Kismet, which will become the primary tracking code in the next release of Kismet.  As such, alerts are available from the client protocol under the standard *ALERT sentence, but will not be attached to the network list in the Kismet UI due to pending changes to code.

Further enhancements to WPS brute force detection may be forthcoming soon depending on development.

To be most effective, Kismet should be locked onto the channel of the AP being monitored, however depending on the frequency of the attack, a channel-hopping instance should also detect it.

[Update] When testing, don't forget to enable the WPABRUTE alert in your kismet.conf!

[Update #2] Also included in Kismet-SVN by popular demand is a basic Ruby client which bridges Kismet alerts to syslog:

Jan 10 11:15:27 drd1812 kismet: WPSBRUTE server-ts=1326212106 bssid=00:14:D1:E6:8F:F8 source=00:14:D1:E6:8F:F8 dest=18:3D:A2:4A:65:80 channel=1 IEEE80211 AP 'rootsdkwlan' (00:14:D1:E6:8F:F8) sending excessive number of WPS messages which may indicate a WPS brute force attack such as Reaver

[Update #3] Kismet-SVN now includes the plugin-alertsyslog server plugin, which also logs alerts to syslog, without needing ruby or needing to run a separate client.

[Update #4] Expanded the timeline for WPS brute detection to 5 minutes to catch more during channel-hop configs.  WPS negotiation is so rare that this shouldn't be triggering false positives even with the expanded window.

Kismet SVN code is available via svn co kismet-devel


I'll be at Shmoocon again this year, running the wifi.  Drop me an email if you want to get a drink or something, or come find me, probably in the NOC.

Warning: I'm often a bit out of it at cons that I'm doing work at, so if I'm a bit scatterbrained, forgive me.

Drone wackiness

Drones are currently slightly broken - the only consolation is that it seems like they've been broken for quite a while now too.

Drones are supposed to tunnel virtual interfaces to kismet_server which correspond to interfaces on the drone.  It looks like this hasn't been happening for some time, and in trying to fix it, I see that there is a LOT of wacky badness happening between drones, channel lists, etc.

Rather than fix this, it's currently shortcut with a "Not making a source" alert and packets appear from the drone source, not the original remote source.  This is because at some point in the near future all the phy-neutral stuff is going to require a complete rewrite of how channel lists are processed.  Rather than dig through ancient code and try to cobble together a fix right now, it's going to have to wait until the channel code is rewritten.

This will also likely change the drone protocol - old drones will likely still be able to report, but are unlikely to be able to control channels under the new model, because the channel will have to be processed as a more complex entity than simply an integer (think "6HT40+" instead of "6" for an example of the problem, and that's just in 802.11 land).

So, hold tight.  For now, drones aren't any more broken than they used to be, and soon they'll be much better.

Thursday, January 5, 2012

Phy-Neutral changes to drones

There's been a slight change in how drones handle things - or rather, changes in how Kismet handles things, which have lead to changes in how drones operate.

Previously, the DLT decode (ie parsing radiotap headers, etc) happened in the drone, and the packet was sent as a decoded kismet radio packet + dot11 mangled chunk.  This never sat well with me since the radio parsing code was fairly complex, and it limited what the drone could report.

With preparations for phy-neutral support for pcap files, the DLT decoding has migrated out of the packet capture sources and into the packet chain; the source is responsible for creating a linkframe record in the packet, and then the postcap chain stage triggers to decode it into the appropriate frame type.

This means:

- Phy-agnostic capture sources like pcapfiles no longer make the assumptions it must be a dot11 capture

- DLT-detection moves into the second-tier classes of pcap-based capture sources (setdlt/checkdlt for dot11 moves into wext, bsd, etc layer)

- Capture sources now solely create a linkframe record, unless they need to do meta-data that isn't encoded in the DLT; directly creating a radio record IS still possible.

- The drone data frame has been DLT-typed for some time now, though always 802.11.  Now the same code defaults down to the linkframe layer and sends the raw radiotap, prism2, or whatever (zigbee?  btbb?) formatted frame.  The only rules are that the DLT type MUST be set equivalently on both ends, and there must be a DLT decoder on the server to handle that DLT type, otherwise the data remains in the linkframe record and is never processed.

- Drones no longer do anything but GPS and packet read; this is more secure, quicker, less code overhead

- Drones CAN still send radio records with a packet, if something comes up w/ a plugin source that reads radio data from outside the packet data stream

This has the nice side effect of being able to play back non-dot11 files if you have the plugins to do so, you can also use PPI on non-dot11 DLTs now as the embedded DLT is carried into the data layer capture record in the PPI decoder.