mirror of
https://github.com/mfontanini/libtins
synced 2026-01-23 02:35:57 +01:00
Add WPA2Decrypter callback interface
This commit is contained in:
@@ -131,6 +131,12 @@ ELSE()
|
||||
MESSAGE(STATUS "Disabling ACK tracking support")
|
||||
ENDIF()
|
||||
|
||||
OPTION(LIBTINS_ENABLE_WPA2_CALLBACKS "Enable WPA2 callback interface" ON)
|
||||
IF(LIBTINS_ENABLE_WPA2_CALLBACKS AND TINS_HAVE_WPA2_DECRYPTION AND TINS_HAVE_CXX11)
|
||||
SET(STATUS "Enabling WPA2 callback interface")
|
||||
SET(TINS_HAVE_WPA2_CALLBACKS ON)
|
||||
ENDIF()
|
||||
|
||||
# Use pcap_sendpacket to send l2 packets rather than raw sockets
|
||||
IF(WIN32)
|
||||
SET(USE_PCAP_SENDPACKET_DEFAULT ON)
|
||||
|
||||
@@ -19,7 +19,7 @@ before_build:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- if "%platform%"=="x64" ( set GENERATOR="Visual Studio 12 Win64" ) else ( set GENERATOR="Visual Studio 12" )
|
||||
- cmake .. -G %GENERATOR% -DPCAP_ROOT_DIR=c:\WpdPack -DLIBTINS_BUILD_SHARED=0
|
||||
- cmake .. -G %GENERATOR% -DPCAP_ROOT_DIR=c:\WpdPack -DLIBTINS_BUILD_SHARED=0 -DLIBTINS_ENABLE_WPA2=0
|
||||
build:
|
||||
project: C:/projects/libtins/build/libtins.sln
|
||||
verbosity: minimal
|
||||
|
||||
@@ -19,4 +19,7 @@
|
||||
/* Have GCC builtin swap */
|
||||
#cmakedefine TINS_HAVE_GCC_BUILTIN_SWAP
|
||||
|
||||
/* Have WPA2Decrypter callbacks */
|
||||
#cmakedefine TINS_HAVE_WPA2_CALLBACKS
|
||||
|
||||
#endif // TINS_CONFIG_H
|
||||
|
||||
@@ -36,6 +36,9 @@
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#ifdef TINS_HAVE_WPA2_CALLBACKS
|
||||
#include <functional>
|
||||
#endif // TINS_HAVE_WPA2_CALLBACKS
|
||||
#include "utils.h"
|
||||
#include "snap.h"
|
||||
#include "rawpdu.h"
|
||||
@@ -160,8 +163,15 @@ public:
|
||||
* \return The generated PMK.
|
||||
*/
|
||||
const pmk_type& pmk() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the SSID
|
||||
* \return The access point's SSID
|
||||
*/
|
||||
const std::string& ssid() const;
|
||||
private:
|
||||
pmk_type pmk_;
|
||||
std::string ssid_;
|
||||
};
|
||||
|
||||
} // WPA2
|
||||
@@ -275,6 +285,32 @@ public:
|
||||
*/
|
||||
typedef std::map<addr_pair, WPA2::SessionKeys> keys_map;
|
||||
|
||||
#ifdef TINS_HAVE_WPA2_CALLBACKS
|
||||
|
||||
/**
|
||||
* \brief The type used to store the callback type used when a new access
|
||||
* point is found.
|
||||
*
|
||||
* The first argument to the function will be the access point's SSID and
|
||||
* the second one its BSSID.
|
||||
*/
|
||||
typedef std::function<void(const std::string&,
|
||||
const address_type&)> ap_found_callback_type;
|
||||
|
||||
/**
|
||||
* The type used to store the callback type used when a new handshake
|
||||
* is captured.
|
||||
*
|
||||
* The first argument to the function will be the access point's SSID and
|
||||
* the second one its BSSID. The third argument will be the client's hardware
|
||||
* address.
|
||||
*/
|
||||
typedef std::function<void(const std::string&,
|
||||
const address_type&,
|
||||
const address_type&)> handshake_captured_callback_type;
|
||||
|
||||
#endif // TINS_HAVE_WPA2_CALLBACKS
|
||||
|
||||
/**
|
||||
* \brief Adds an access points's information.
|
||||
*
|
||||
@@ -353,6 +389,30 @@ public:
|
||||
*/
|
||||
bool decrypt(PDU& pdu);
|
||||
|
||||
#ifdef TINS_HAVE_WPA2_CALLBACKS
|
||||
/**
|
||||
* \brief Sets the handshake captured callback
|
||||
*
|
||||
* This callback will be executed every time a new handshake is captured.
|
||||
*
|
||||
* \sa handshake_captured_callback_type
|
||||
* \param callback The new callback to be set
|
||||
*/
|
||||
void handshake_captured_callback(const handshake_captured_callback_type& callback);
|
||||
|
||||
/**
|
||||
* \brief Sets the access point found callback
|
||||
*
|
||||
* This callback will be executed every time a new access point is found, that's
|
||||
* advertising an SSID added when calling add_ap_data.
|
||||
*
|
||||
* \sa ap_found_callback_type
|
||||
* \param callback The new callback to be set
|
||||
*/
|
||||
void ap_found_callback(const ap_found_callback_type& callback);
|
||||
|
||||
#endif // TINS_HAVE_WPA2_CALLBACKS
|
||||
|
||||
/**
|
||||
* \brief Getter for the keys on this decrypter
|
||||
*
|
||||
@@ -381,6 +441,10 @@ private:
|
||||
pmks_map pmks_;
|
||||
bssids_map aps_;
|
||||
keys_map keys_;
|
||||
#ifdef TINS_HAVE_WPA2_CALLBACKS
|
||||
handshake_captured_callback_type handshake_captured_callback_;
|
||||
ap_found_callback_type ap_found_callback_;
|
||||
#endif // TINS_HAVE_WPA2_CALLBACKS
|
||||
};
|
||||
#endif // TINS_HAVE_WPA2_DECRYPTION
|
||||
|
||||
|
||||
@@ -491,7 +491,7 @@ bool SessionKeys::uses_ccmp() const {
|
||||
// supplicant_data
|
||||
|
||||
SupplicantData::SupplicantData(const string& psk, const string& ssid)
|
||||
: pmk_(SessionKeys::PMK_SIZE) {
|
||||
: pmk_(SessionKeys::PMK_SIZE), ssid_(ssid) {
|
||||
PKCS5_PBKDF2_HMAC_SHA1(
|
||||
psk.c_str(),
|
||||
psk.size(),
|
||||
@@ -506,6 +506,11 @@ SupplicantData::SupplicantData(const string& psk, const string& ssid)
|
||||
const SupplicantData::pmk_type& SupplicantData::pmk() const {
|
||||
return pmk_;
|
||||
}
|
||||
|
||||
const string& SupplicantData::ssid() const {
|
||||
return ssid_;
|
||||
}
|
||||
|
||||
} // namespace WPA2
|
||||
|
||||
void WPA2Decrypter::add_ap_data(const string& psk, const string& ssid) {
|
||||
@@ -525,6 +530,12 @@ void WPA2Decrypter::add_access_point(const string& ssid, const address_type& add
|
||||
throw runtime_error("Supplicant data not registered");
|
||||
}
|
||||
aps_.insert(make_pair(addr, it->second));
|
||||
|
||||
#ifdef TINS_HAVE_WPA2_CALLBACKS
|
||||
if (ap_found_callback_) {
|
||||
ap_found_callback_(ssid, addr);
|
||||
}
|
||||
#endif // TINS_HAVE_WPA2_CALLBACKS
|
||||
}
|
||||
|
||||
void WPA2Decrypter::add_decryption_keys(const addr_pair& addresses,
|
||||
@@ -540,6 +551,12 @@ void WPA2Decrypter::try_add_keys(const Dot11Data& dot11, const RSNHandshake& hs)
|
||||
try {
|
||||
SessionKeys session(hs, it->second.pmk());
|
||||
keys_[addr_p] = session;
|
||||
#ifdef TINS_HAVE_WPA2_CALLBACKS
|
||||
if (handshake_captured_callback_) {
|
||||
handshake_captured_callback_(it->second.ssid(), addr_p.first,
|
||||
addr_p.second);
|
||||
}
|
||||
#endif // TINS_HAVE_WPA2_CALLBACKS
|
||||
}
|
||||
catch(WPA2::invalid_handshake&) {
|
||||
|
||||
@@ -629,6 +646,18 @@ bool WPA2Decrypter::decrypt(PDU& pdu) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef TINS_HAVE_WPA2_CALLBACKS
|
||||
|
||||
void WPA2Decrypter::handshake_captured_callback(const handshake_captured_callback_type& callback) {
|
||||
handshake_captured_callback_ = callback;
|
||||
}
|
||||
|
||||
void WPA2Decrypter::ap_found_callback(const ap_found_callback_type& callback) {
|
||||
ap_found_callback_ = callback;
|
||||
}
|
||||
|
||||
#endif // TINS_HAVE_WPA2_CALLBACKS
|
||||
|
||||
#endif // TINS_HAVE_WPA2_DECRYPTION
|
||||
|
||||
} // namespace Crypto
|
||||
|
||||
@@ -8,22 +8,59 @@
|
||||
#include <stdint.h>
|
||||
#include "crypto.h"
|
||||
#include "radiotap.h"
|
||||
#include "dot11/dot11_data.h"
|
||||
#include "udp.h"
|
||||
#include "tcp.h"
|
||||
|
||||
using namespace Tins;
|
||||
|
||||
using std::string;
|
||||
using std::vector;
|
||||
|
||||
class WPA2DecryptTest : public testing::Test {
|
||||
public:
|
||||
typedef HWAddress<6> address_type;
|
||||
static const uint8_t ccmp_packets[7][652];
|
||||
static const uint8_t tkip_packets[7][211];
|
||||
static const size_t ccmp_packets_size[], tkip_packets_size[];
|
||||
|
||||
struct handshake {
|
||||
handshake(const string& ssid, const address_type& bssid, const address_type& client_hw)
|
||||
: ssid(ssid), bssid(bssid), client_hw(client_hw) {
|
||||
|
||||
}
|
||||
|
||||
string ssid;
|
||||
address_type bssid;
|
||||
address_type client_hw;
|
||||
};
|
||||
|
||||
struct ap_data {
|
||||
ap_data(const string& ssid, const address_type& bssid)
|
||||
: ssid(ssid), bssid(bssid) {
|
||||
|
||||
}
|
||||
|
||||
string ssid;
|
||||
address_type bssid;
|
||||
};
|
||||
|
||||
void check_ccmp_packet5(const PDU& pdu);
|
||||
void check_ccmp_packet6(const PDU& pdu);
|
||||
|
||||
void check_tkip_packet5(const PDU& pdu);
|
||||
void check_tkip_packet6(const PDU& pdu);
|
||||
|
||||
void handshake_captured(const string& ssid, const address_type& bssid, const address_type& client_hw) {
|
||||
handshakes_.push_back(handshake(ssid, bssid, client_hw));
|
||||
}
|
||||
|
||||
void ap_found(const string& ssid, const address_type& bssid) {
|
||||
access_points_.push_back(ap_data(ssid, bssid));
|
||||
}
|
||||
|
||||
vector<handshake> handshakes_;
|
||||
vector<ap_data> access_points_;
|
||||
};
|
||||
|
||||
// packet taken from aircrack's site.
|
||||
@@ -283,4 +320,63 @@ TEST_F(WPA2DecryptTest, DecryptCCMPAndTKIPWithoutUsingBeacon) {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef TINS_HAVE_WPA2_CALLBACKS
|
||||
|
||||
TEST_F(WPA2DecryptTest, HandshakeCapturedCallback) {
|
||||
using namespace std::placeholders;
|
||||
|
||||
Crypto::WPA2Decrypter decrypter;
|
||||
decrypter.add_ap_data("libtinstest", "NODO", "00:1b:11:d2:1b:eb");
|
||||
decrypter.add_ap_data("Induction", "Coherer", "00:0c:41:82:b2:55");
|
||||
decrypter.handshake_captured_callback(std::bind(&WPA2DecryptTest::handshake_captured,
|
||||
this, _1, _2, _3));
|
||||
for(size_t i = 1; i < 7; ++i) {
|
||||
RadioTap radio(ccmp_packets[i], ccmp_packets_size[i]);
|
||||
decrypter.decrypt(radio);
|
||||
}
|
||||
for(size_t i = 1; i < 7; ++i) {
|
||||
RadioTap radio(tkip_packets[i], tkip_packets_size[i]);
|
||||
decrypter.decrypt(radio);
|
||||
}
|
||||
|
||||
ASSERT_EQ(2, handshakes_.size());
|
||||
handshake hs = handshakes_[0];
|
||||
EXPECT_EQ(hs.ssid, "Coherer");
|
||||
EXPECT_EQ(address_type("00:0d:93:82:36:3a"), hs.client_hw);
|
||||
EXPECT_EQ(address_type("00:0c:41:82:b2:55"), hs.bssid);
|
||||
|
||||
hs = handshakes_[1];
|
||||
EXPECT_EQ(hs.ssid, "NODO");
|
||||
EXPECT_EQ(address_type("94:0c:6d:8f:93:88"), hs.client_hw);
|
||||
EXPECT_EQ(address_type("00:1b:11:d2:1b:eb"), hs.bssid);
|
||||
}
|
||||
|
||||
TEST_F(WPA2DecryptTest, AccessPointFoundCallback) {
|
||||
using namespace std::placeholders;
|
||||
|
||||
Crypto::WPA2Decrypter decrypter;
|
||||
decrypter.add_ap_data("libtinstest", "NODO");
|
||||
decrypter.add_ap_data("Induction", "Coherer");
|
||||
decrypter.ap_found_callback(std::bind(&WPA2DecryptTest::ap_found, this, _1, _2));
|
||||
for(size_t i = 0; i < 7; ++i) {
|
||||
RadioTap radio(ccmp_packets[i], ccmp_packets_size[i]);
|
||||
decrypter.decrypt(radio);
|
||||
}
|
||||
for(size_t i = 0; i < 7; ++i) {
|
||||
RadioTap radio(tkip_packets[i], tkip_packets_size[i]);
|
||||
decrypter.decrypt(radio);
|
||||
}
|
||||
|
||||
ASSERT_EQ(2, access_points_.size());
|
||||
ap_data data = access_points_[0];
|
||||
EXPECT_EQ("Coherer", data.ssid);
|
||||
EXPECT_EQ(address_type("00:0c:41:82:b2:55"), data.bssid);
|
||||
|
||||
data = access_points_[1];
|
||||
EXPECT_EQ("NODO", data.ssid);
|
||||
EXPECT_EQ(address_type("00:1b:11:d2:1b:eb"), data.bssid);
|
||||
}
|
||||
|
||||
#endif // TINS_HAVE_WPA2_CALLBACKS
|
||||
|
||||
#endif // defined(TINS_HAVE_DOT11) && defined(TINS_HAVE_WPA2_DECRYPTION)
|
||||
|
||||
Reference in New Issue
Block a user