From 17d351cb822627e4d1e6997a2c859861b595a80d Mon Sep 17 00:00:00 2001 From: Matias Fontanini Date: Wed, 10 Oct 2012 23:37:16 -0300 Subject: [PATCH] Added support for decrypting WEP encrypted packets on the fly. --- depends.d | 80 +++++++++++++++- include/crypto.h | 234 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 309 insertions(+), 5 deletions(-) create mode 100644 include/crypto.h diff --git a/depends.d b/depends.d index 257d3a4..23b82ef 100644 --- a/depends.d +++ b/depends.d @@ -41,6 +41,34 @@ include/endianness.h: include/ip_address.h: include/hw_address.h: +src/crypto.o: src/crypto.cpp include/crypto.h include/dot11.h \ + include/pdu.h include/endianness.h include/hw_address.h \ + include/small_uint.h include/pdu_option.h include/network_interface.h \ + include/ip_address.h include/utils.h include/snap.h include/rawpdu.h + +include/crypto.h: + +include/dot11.h: + +include/pdu.h: + +include/endianness.h: + +include/hw_address.h: + +include/small_uint.h: + +include/pdu_option.h: + +include/network_interface.h: + +include/ip_address.h: + +include/utils.h: + +include/snap.h: + +include/rawpdu.h: src/dhcp.o: src/dhcp.cpp include/endianness.h include/dhcp.h \ include/bootp.h include/pdu.h include/endianness.h include/ip_address.h \ include/hw_address.h include/pdu_option.h include/ethernetII.h \ @@ -141,7 +169,8 @@ include/rsn_information.h: src/ethernetII.o: src/ethernetII.cpp include/ethernetII.h include/pdu.h \ include/endianness.h include/hw_address.h include/network_interface.h \ include/ip_address.h include/packet_sender.h include/rawpdu.h \ - include/ip.h include/small_uint.h include/pdu_option.h include/arp.h + include/ip.h include/small_uint.h include/pdu_option.h include/arp.h \ + include/constants.h include/ethernetII.h: @@ -166,6 +195,8 @@ include/small_uint.h: include/pdu_option.h: include/arp.h: + +include/constants.h: src/icmp.o: src/icmp.cpp include/icmp.h include/pdu.h \ include/endianness.h include/rawpdu.h include/utils.h \ include/ip_address.h include/hw_address.h @@ -252,6 +283,30 @@ include/pdu.h: include/endianness.h: +include/rawpdu.h: +src/loopback.o: src/loopback.cpp include/loopback.h include/pdu.h \ + include/packet_sender.h include/ip.h include/small_uint.h \ + include/endianness.h include/ip_address.h include/pdu_option.h \ + include/llc.h include/rawpdu.h + +include/loopback.h: + +include/pdu.h: + +include/packet_sender.h: + +include/ip.h: + +include/small_uint.h: + +include/endianness.h: + +include/ip_address.h: + +include/pdu_option.h: + +include/llc.h: + include/rawpdu.h: src/network_interface.o: src/network_interface.cpp \ include/network_interface.h include/hw_address.h include/ip_address.h \ @@ -353,7 +408,9 @@ include/pdu_option.h: include/eapol.h: src/sniffer.o: src/sniffer.cpp include/sniffer.h include/pdu.h \ include/ethernetII.h include/endianness.h include/hw_address.h \ - include/network_interface.h include/ip_address.h include/radiotap.h + include/network_interface.h include/ip_address.h include/radiotap.h \ + include/loopback.h include/dot11.h include/small_uint.h \ + include/pdu_option.h include/sniffer.h: @@ -370,6 +427,14 @@ include/network_interface.h: include/ip_address.h: include/radiotap.h: + +include/loopback.h: + +include/dot11.h: + +include/small_uint.h: + +include/pdu_option.h: src/tcp.o: src/tcp.cpp include/tcp.h include/pdu.h include/endianness.h \ include/small_uint.h include/pdu_option.h include/ip.h \ include/ip_address.h include/constants.h include/rawpdu.h \ @@ -399,8 +464,9 @@ include/hw_address.h: src/tcp_stream.o: src/tcp_stream.cpp include/rawpdu.h include/pdu.h \ include/tcp_stream.h include/sniffer.h include/ethernetII.h \ include/endianness.h include/hw_address.h include/network_interface.h \ - include/ip_address.h include/radiotap.h include/tcp.h \ - include/small_uint.h include/pdu_option.h include/ip.h + include/ip_address.h include/radiotap.h include/loopback.h \ + include/dot11.h include/small_uint.h include/pdu_option.h include/tcp.h \ + include/ip.h include/rawpdu.h: @@ -422,12 +488,16 @@ include/ip_address.h: include/radiotap.h: -include/tcp.h: +include/loopback.h: + +include/dot11.h: include/small_uint.h: include/pdu_option.h: +include/tcp.h: + include/ip.h: src/udp.o: src/udp.cpp include/udp.h include/pdu.h include/endianness.h \ include/constants.h include/utils.h include/ip_address.h \ diff --git a/include/crypto.h b/include/crypto.h new file mode 100644 index 0000000..25cd45b --- /dev/null +++ b/include/crypto.h @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2012, Nasel + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef TINS_CRYPTO_H +#define TINS_CRYPTO_H + +#include +#include +#include +#include +#include "dot11.h" +#include "utils.h" +#include "snap.h" +#include "rawpdu.h" + +namespace Tins { +class PDU; + +namespace Crypto { + /** + * \brief RC4 Key abstraction. + */ + struct RC4Key { + static const size_t data_size = 256; + + /** + * \brief Initializes the key using the provided iterator range. + * + * \param start The start of the range. + * \param end The end of the range. + */ + template + RC4Key(ForwardIterator start, ForwardIterator end); + + /** + * The actual key data. + */ + uint8_t data[data_size]; + }; + + /** + * + */ + template + class WEPDecrypter { + public: + typedef Dot11::address_type address_type; + + /** + * \brief Constructs a WEPDecrypter from a Functor object. + * + * \param func The functor which will be used to handle decrypted + * packets. + */ + WEPDecrypter(Functor func); + + /** + * \brief Adds a decryption password. + * + * \param addr The access point's BSSID. + * \param password The password which will be used to decrypt + * packets sent from and to the AP identifier by the BSSID addr. + */ + void add_password(const address_type &addr, const std::string &password); + + /** + * \brief Removes a decryption password + * + * \param addr The BSSID of the access point. + */ + void remove_password(const address_type &addr); + + /** + * \brief Decrypts the provided PDU and forwards the decrypted + * PDU to the functor held by this object. + * + * A Dot11Data PDU is looked up inside the provided PDU chain. + * If no such PDU exists or there is no password associated + * with the Dot11 packet's BSSID, then the functor is called + * using the pdu parameter as its argument. + * + * Otherwise, the packet is decrypted using the given password + * and the functor is called using the decrypted packet as its + * argument. If the CRC found after decrypting it is invalid, + * then the packet is discarded. + * + */ + bool operator()(PDU &pdu); + private: + typedef std::map passwords_type; + + PDU *decrypt(RawPDU &raw, const std::string &password); + + Functor functor; + passwords_type passwords; + std::vector key_buffer; + }; + + template + void rc4(ForwardIterator start, ForwardIterator end, RC4Key &key, OutputIterator output); + + + // Implementation section + + // WEP Decrypter + + template + WEPDecrypter::WEPDecrypter(Functor func) + : functor(func), key_buffer(4) { + + } + + template + void WEPDecrypter::add_password(const address_type &addr, const std::string &password) { + passwords[addr] = password; + key_buffer.resize(std::max(3 + password.size(), key_buffer.size())); + } + + template + void WEPDecrypter::remove_password(const address_type &addr) { + passwords.erase(addr); + } + + template + bool WEPDecrypter::operator() (PDU &pdu) { + Dot11Data *dot11 = pdu.find_pdu(); + if(dot11) { + RawPDU *raw = dot11->find_pdu(); + if(raw) { + address_type addr; + if(!dot11->from_ds() && !dot11->to_ds()) + addr = dot11->addr3(); + else if(!dot11->from_ds() && dot11->to_ds()) + addr = dot11->addr1(); + else if(dot11->from_ds() && !dot11->to_ds()) + addr = dot11->addr2(); + else + // ???? + addr = dot11->addr3(); + passwords_type::iterator it = passwords.find(addr); + if(it != passwords.end()) { + dot11->inner_pdu(decrypt(*raw, it->second)); + // Invalid WEP packet(CRC check failed). Skip it. + if(!dot11->inner_pdu()) + return true; + } + } + } + return functor(pdu); + } + + template + PDU *WEPDecrypter::decrypt(RawPDU &raw, const std::string &password) { + RawPDU::payload_type &pload = raw.payload(); + // We require at least the IV, the encrypted checksum and something to decrypt + if(pload.size() <= 8) + return 0; + std::copy(pload.begin(), pload.begin() + 3, key_buffer.begin()); + std::copy(password.begin(), password.end(), key_buffer.begin() + 3); + + // Generate the key + RC4Key key(key_buffer.begin(), key_buffer.begin() + password.size() + 3); + rc4(pload.begin() + 4, pload.end(), key, pload.begin()); + uint32_t crc = Utils::crc32(&pload[0], pload.size() - 8); + if(pload[pload.size() - 8] != (crc & 0xff) || + pload[pload.size() - 7] != ((crc >> 8) & 0xff) || + pload[pload.size() - 6] != ((crc >> 16) & 0xff) || + pload[pload.size() - 5] != ((crc >> 24) & 0xff)) + return 0; + + try { + return new SNAP(&pload[0], pload.size() - 8); + } + catch(std::runtime_error&) { + return 0; + } + } + + // RC4 stuff + + template + RC4Key::RC4Key(ForwardIterator start, ForwardIterator end) { + for(size_t i = 0; i < data_size; ++i) + data[i] = i; + size_t j = 0; + ForwardIterator iter = start; + for(size_t i = 0; i < data_size; ++i) { + j = (j + data[i] + *iter++) % 256; + if(iter == end) + iter = start; + std::swap(data[i], data[j]); + } + } + + template + void rc4(ForwardIterator start, ForwardIterator end, RC4Key &key, OutputIterator output) { + size_t i = 0, j = 0; + while(start != end) { + i = (i + 1) % RC4Key::data_size; + j = (j + key.data[i]) % RC4Key::data_size; + std::swap(key.data[i], key.data[j]); + *output++ = *start++ ^ key.data[(key.data[i] + key.data[j]) % RC4Key::data_size]; + } + } +} +} + +#endif // TINS_CRYPTO_H