Skip to content

Commit

Permalink
Added attack failure handling
Browse files Browse the repository at this point in the history
Added DictionaryGuesser
  • Loading branch information
jgehring committed Feb 7, 2010
1 parent cb67b05 commit 8e75997
Show file tree
Hide file tree
Showing 10 changed files with 190 additions and 18 deletions.
1 change: 1 addition & 0 deletions src/Makefile.am
Expand Up @@ -24,6 +24,7 @@ pgpry_SOURCES = \
guessers/charsteguesser.h guessers/charsetguesser.cpp \
guessers/incguesser.h guessers/incguesser.cpp \
guessers/randomguesser.h guessers/randomguesser.cpp \
guessers/dictguesser.h guessers/dictguesser.cpp \
\
crackers/crackers.h crackers/crackers.cpp \
crackers/cast5crackers.h crackers/cast5crackers.cpp \
Expand Down
29 changes: 25 additions & 4 deletions src/attack.cpp
Expand Up @@ -23,10 +23,11 @@
// Static variables
Key Attack::m_key;
Memblock Attack::m_phrase;
Buffer *Attack::m_buffer = NULL;
std::vector<Guessers::Guesser *> Attack::m_guessers;
std::vector<RegexFilter *> Attack::m_regexFilters;
std::vector<Crackers::Cracker *> Attack::m_crackers;
bool Attack::m_success = false;
Attack::Status Attack::m_status;
SysUtils::Mutex Attack::m_mutex;
SysUtils::WaitCondition Attack::m_condition;

Expand All @@ -35,7 +36,7 @@ SysUtils::WaitCondition Attack::m_condition;
int32_t Attack::run(const Key &key, const Options &options)
{
Attack::m_key = key;
Attack::m_success = false;
Attack::m_status = STATUS_RUNNING;

// Setup threads
Buffer buffer, buffer2;
Expand All @@ -54,6 +55,7 @@ int32_t Attack::run(const Key &key, const Options &options)
return EXIT_FAILURE;
}

Attack::m_buffer = &buffer;
Attack::m_mutex.lock();

// Start threads
Expand All @@ -70,7 +72,7 @@ int32_t Attack::run(const Key &key, const Options &options)
// Now all we've got to do is wait
Attack::m_condition.wait(&Attack::m_mutex);

if (Attack::m_success) {
if (Attack::m_status == STATUS_SUCCESS) {
std::cout << "SUCCESS: Found pass phrase: '" << m_phrase.data << "'." << std::endl;
} else {
std::cout << "SORRY, the key space is exhausted. The attack failed." << std::endl;
Expand Down Expand Up @@ -98,13 +100,32 @@ void Attack::phraseFound(const Memblock &mblock)
// TODO: Check the solution once more by trying to unlock the key

Attack::m_mutex.lock();
Attack::m_success = true;
Attack::m_status = STATUS_SUCCESS;

Attack::m_phrase = mblock;
Attack::m_condition.wakeAll();
Attack::m_mutex.unlock();
}

// Called by a guesser if it's out of phrases
void Attack::exhausted()
{
Attack::m_mutex.lock();
Attack::m_status = STATUS_FAILURE;
Attack::m_mutex.unlock();

// Insert empty memory blocks into the buffer. The cracker thread will finish
// if the attack status isn't RUNNING and it received an empty memory block from the buffer
uint32_t n = Attack::m_buffer->size();
for (uint32_t i = 0; i < n; i++) {
Attack::m_buffer->put(Memblock());
}

Attack::m_mutex.lock();
Attack::m_condition.wakeAll();
Attack::m_mutex.unlock();
}

// Sets up the pass phrases guessers
std::vector<Guessers::Guesser *> Attack::setupGuessers(Buffer *out, const Options &options)
{
Expand Down
23 changes: 17 additions & 6 deletions src/attack.h
Expand Up @@ -32,11 +32,21 @@ namespace Guessers {

class Attack
{
public:
enum Status
{
STATUS_RUNNING = 0,
STATUS_SUCCESS = 1,
STATUS_FAILURE = 2
};

public:
static int32_t run(const Key &key, const Options &options);

static void phraseFound(const Memblock &mblock);
static bool successful();
static void exhausted();

static Status status();

private:
static std::vector<Guessers::Guesser *> setupGuessers(Buffer *out, const Options &options);
Expand All @@ -46,23 +56,24 @@ class Attack
private:
static Key m_key;
static Memblock m_phrase;
static Buffer *m_buffer;
static std::vector<Guessers::Guesser *> m_guessers;
static std::vector<RegexFilter *> m_regexFilters;
static std::vector<Crackers::Cracker *> m_crackers;
static bool m_success;
static Status m_status;
static SysUtils::Mutex m_mutex;
static SysUtils::WaitCondition m_condition;
};


// Inlined functions
inline bool Attack::successful()
inline Attack::Status Attack::status()
{
bool success;
Status status;
Attack::m_mutex.lock();
success = Attack::m_success;
status = Attack::m_status;
Attack::m_mutex.unlock();
return success;
return status;
}


Expand Down
14 changes: 11 additions & 3 deletions src/crackers/crackers.cpp
Expand Up @@ -45,15 +45,23 @@ void Cracker::run()
numBlocks = m_buffer->taken(8, blocks);

for (uint32_t i = 0; i < numBlocks; i++) {
if (check(blocks[i].data, blocks[i].length)) {
if (blocks[i].length > 0 && check(blocks[i].data, blocks[i].length)) {
Attack::phraseFound(blocks[i]);
}
}

// Avoid constant status querying
if (++n > 128) {
if (Attack::successful()) {
break;
switch (Attack::status()) {
case Attack::STATUS_SUCCESS:
return;
case Attack::STATUS_FAILURE:
if (blocks[0].length == 0) {
return;
}
break;
default:
break;
}
n = 0;
}
Expand Down
2 changes: 0 additions & 2 deletions src/guessers/charsetguesser.h
Expand Up @@ -11,8 +11,6 @@
#define CHARSETGUESSER_H_


#include "main.h"

#include "guessers.h"


Expand Down
70 changes: 70 additions & 0 deletions src/guessers/dictguesser.cpp
@@ -0,0 +1,70 @@
/*
* pgpry alpha - PGP private key password recovery
* Copyright (C) 2010 Jonas Gehring
*
* file: dictguesser.cpp
* Simple dictionary guesser
*/


#include <fstream>
#include <iostream>

#include "dictguesser.h"


namespace Guessers
{

// Constructor
DictionaryGuesser::DictionaryGuesser(Buffer *buffer)
: Guesser(buffer), m_index(0)
{

}

void DictionaryGuesser::setup(const std::map<std::string, std::string> &options)
{
std::map<std::string, std::string>::const_iterator it;

m_dictfile = std::string();
it = options.find("dictionary");
if (it != options.end()) {
m_dictfile = (*it).second;
}

m_index = 0;
m_phrases.clear();
}

bool DictionaryGuesser::init()
{
std::ifstream in(m_dictfile.c_str());
if (in.fail()) {
std::cerr << "Error: Unable to open file " << m_dictfile << std::endl;
return false;
}

std::string str;
while (in.good()) {
getline(in, str);

if (!str.empty()) {
m_phrases.push_back(Memblock(str.c_str()));
}
}

return true;
}

bool DictionaryGuesser::guess(Memblock *m)
{
if (m_index >= m_phrases.size()) {
return false;
}

*m = m_phrases[m_index++];
return true;
}

} // namespace Guessers
45 changes: 45 additions & 0 deletions src/guessers/dictguesser.h
@@ -0,0 +1,45 @@
/*
* pgpry alpha - PGP private key password recovery
* Copyright (C) 2010 Jonas Gehring
*
* file: dictguesser.h
* Simple dictionary guesser
*/


#ifndef DICTGUESSER_H_
#define DICTGUESSER_H_


#include <string>
#include <vector>

#include "guessers.h"

#include "memblock.h"


namespace Guessers
{

class DictionaryGuesser : public Guesser
{
public:
DictionaryGuesser(Buffer *buffer);

void setup(const std::map<std::string, std::string> &options);

protected:
bool init();
bool guess(Memblock *m);

protected:
std::string m_dictfile;
uint32_t m_index;
std::vector<Memblock> m_phrases;
};

} // namespace Guessers


#endif // DICTGUESSER_H_
10 changes: 9 additions & 1 deletion src/guessers/guessers.cpp
Expand Up @@ -15,6 +15,7 @@

#include "guessers.h"

#include "dictguesser.h"
#include "incguesser.h"
#include "randomguesser.h"

Expand Down Expand Up @@ -69,9 +70,14 @@ void Guesser::run()
n = 0;
}

if (numBlocks != 8) {
Attack::exhausted();
break;
}

// Avoid constant status querying
if (!(n & 0x7F)) {
if (Attack::successful()) {
if (Attack::status() != Attack::STATUS_RUNNING) {
break;
}
}
Expand All @@ -92,6 +98,8 @@ Guesser *guesser(const std::string &name, Buffer *buffer)
return new IncrementalGuesser(buffer);
} else if (name == "random") {
return new RandomGuesser(buffer);
} else if (name == "dictionary") {
return new DictionaryGuesser(buffer);
}
return NULL;
}
Expand Down
2 changes: 2 additions & 0 deletions src/guessers/guessers.h
Expand Up @@ -11,6 +11,8 @@
#define GUESSERS_H_


#include "main.h"

#include <map>
#include <string>

Expand Down
12 changes: 10 additions & 2 deletions src/regexfilter.cpp
Expand Up @@ -92,8 +92,16 @@ void RegexFilter::run()

// Avoid constant status querying
if (++n > 128) {
if (Attack::successful()) {
break;
switch (Attack::status()) {
case Attack::STATUS_SUCCESS:
return;
case Attack::STATUS_FAILURE:
if (m.length == 0) {
return;
}
break;
default:
break;
}
n = 0;
}
Expand Down

0 comments on commit 8e75997

Please sign in to comment.