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")
|
MESSAGE(STATUS "Disabling ACK tracking support")
|
||||||
ENDIF()
|
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
|
# Use pcap_sendpacket to send l2 packets rather than raw sockets
|
||||||
IF(WIN32)
|
IF(WIN32)
|
||||||
SET(USE_PCAP_SENDPACKET_DEFAULT ON)
|
SET(USE_PCAP_SENDPACKET_DEFAULT ON)
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ before_build:
|
|||||||
- mkdir build
|
- mkdir build
|
||||||
- cd build
|
- cd build
|
||||||
- if "%platform%"=="x64" ( set GENERATOR="Visual Studio 12 Win64" ) else ( set GENERATOR="Visual Studio 12" )
|
- 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:
|
build:
|
||||||
project: C:/projects/libtins/build/libtins.sln
|
project: C:/projects/libtins/build/libtins.sln
|
||||||
verbosity: minimal
|
verbosity: minimal
|
||||||
|
|||||||
@@ -19,4 +19,7 @@
|
|||||||
/* Have GCC builtin swap */
|
/* Have GCC builtin swap */
|
||||||
#cmakedefine TINS_HAVE_GCC_BUILTIN_SWAP
|
#cmakedefine TINS_HAVE_GCC_BUILTIN_SWAP
|
||||||
|
|
||||||
|
/* Have WPA2Decrypter callbacks */
|
||||||
|
#cmakedefine TINS_HAVE_WPA2_CALLBACKS
|
||||||
|
|
||||||
#endif // TINS_CONFIG_H
|
#endif // TINS_CONFIG_H
|
||||||
|
|||||||
@@ -36,6 +36,9 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#ifdef TINS_HAVE_WPA2_CALLBACKS
|
||||||
|
#include <functional>
|
||||||
|
#endif // TINS_HAVE_WPA2_CALLBACKS
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "snap.h"
|
#include "snap.h"
|
||||||
#include "rawpdu.h"
|
#include "rawpdu.h"
|
||||||
@@ -160,8 +163,15 @@ public:
|
|||||||
* \return The generated PMK.
|
* \return The generated PMK.
|
||||||
*/
|
*/
|
||||||
const pmk_type& pmk() const;
|
const pmk_type& pmk() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Getter for the SSID
|
||||||
|
* \return The access point's SSID
|
||||||
|
*/
|
||||||
|
const std::string& ssid() const;
|
||||||
private:
|
private:
|
||||||
pmk_type pmk_;
|
pmk_type pmk_;
|
||||||
|
std::string ssid_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // WPA2
|
} // WPA2
|
||||||
@@ -275,6 +285,32 @@ public:
|
|||||||
*/
|
*/
|
||||||
typedef std::map<addr_pair, WPA2::SessionKeys> keys_map;
|
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.
|
* \brief Adds an access points's information.
|
||||||
*
|
*
|
||||||
@@ -353,6 +389,30 @@ public:
|
|||||||
*/
|
*/
|
||||||
bool decrypt(PDU& pdu);
|
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
|
* \brief Getter for the keys on this decrypter
|
||||||
*
|
*
|
||||||
@@ -381,6 +441,10 @@ private:
|
|||||||
pmks_map pmks_;
|
pmks_map pmks_;
|
||||||
bssids_map aps_;
|
bssids_map aps_;
|
||||||
keys_map keys_;
|
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
|
#endif // TINS_HAVE_WPA2_DECRYPTION
|
||||||
|
|
||||||
|
|||||||
@@ -491,7 +491,7 @@ bool SessionKeys::uses_ccmp() const {
|
|||||||
// supplicant_data
|
// supplicant_data
|
||||||
|
|
||||||
SupplicantData::SupplicantData(const string& psk, const string& ssid)
|
SupplicantData::SupplicantData(const string& psk, const string& ssid)
|
||||||
: pmk_(SessionKeys::PMK_SIZE) {
|
: pmk_(SessionKeys::PMK_SIZE), ssid_(ssid) {
|
||||||
PKCS5_PBKDF2_HMAC_SHA1(
|
PKCS5_PBKDF2_HMAC_SHA1(
|
||||||
psk.c_str(),
|
psk.c_str(),
|
||||||
psk.size(),
|
psk.size(),
|
||||||
@@ -506,6 +506,11 @@ SupplicantData::SupplicantData(const string& psk, const string& ssid)
|
|||||||
const SupplicantData::pmk_type& SupplicantData::pmk() const {
|
const SupplicantData::pmk_type& SupplicantData::pmk() const {
|
||||||
return pmk_;
|
return pmk_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const string& SupplicantData::ssid() const {
|
||||||
|
return ssid_;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace WPA2
|
} // namespace WPA2
|
||||||
|
|
||||||
void WPA2Decrypter::add_ap_data(const string& psk, const string& ssid) {
|
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");
|
throw runtime_error("Supplicant data not registered");
|
||||||
}
|
}
|
||||||
aps_.insert(make_pair(addr, it->second));
|
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,
|
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 {
|
try {
|
||||||
SessionKeys session(hs, it->second.pmk());
|
SessionKeys session(hs, it->second.pmk());
|
||||||
keys_[addr_p] = session;
|
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&) {
|
catch(WPA2::invalid_handshake&) {
|
||||||
|
|
||||||
@@ -629,6 +646,18 @@ bool WPA2Decrypter::decrypt(PDU& pdu) {
|
|||||||
return false;
|
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
|
#endif // TINS_HAVE_WPA2_DECRYPTION
|
||||||
|
|
||||||
} // namespace Crypto
|
} // namespace Crypto
|
||||||
|
|||||||
@@ -8,22 +8,59 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "crypto.h"
|
#include "crypto.h"
|
||||||
#include "radiotap.h"
|
#include "radiotap.h"
|
||||||
|
#include "dot11/dot11_data.h"
|
||||||
#include "udp.h"
|
#include "udp.h"
|
||||||
#include "tcp.h"
|
#include "tcp.h"
|
||||||
|
|
||||||
using namespace Tins;
|
using namespace Tins;
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
using std::vector;
|
||||||
|
|
||||||
class WPA2DecryptTest : public testing::Test {
|
class WPA2DecryptTest : public testing::Test {
|
||||||
public:
|
public:
|
||||||
|
typedef HWAddress<6> address_type;
|
||||||
static const uint8_t ccmp_packets[7][652];
|
static const uint8_t ccmp_packets[7][652];
|
||||||
static const uint8_t tkip_packets[7][211];
|
static const uint8_t tkip_packets[7][211];
|
||||||
static const size_t ccmp_packets_size[], tkip_packets_size[];
|
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_packet5(const PDU& pdu);
|
||||||
void check_ccmp_packet6(const PDU& pdu);
|
void check_ccmp_packet6(const PDU& pdu);
|
||||||
|
|
||||||
void check_tkip_packet5(const PDU& pdu);
|
void check_tkip_packet5(const PDU& pdu);
|
||||||
void check_tkip_packet6(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.
|
// 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)
|
#endif // defined(TINS_HAVE_DOT11) && defined(TINS_HAVE_WPA2_DECRYPTION)
|
||||||
|
|||||||
Reference in New Issue
Block a user