** This is for a college class, I am not actually trying to crack passwords ** Below is my source code, but essentially what I want to have happen is the parent process en queues passwords into an std::list<> attemptList. Then child threads grab from the front of the queue and, currently, just print out the value.
As you can see by the code below I try using std::mutex to block the attemptList when the front is being popped, but both threads are blowing past the lock at the same time and reading from the front. Then one of them segmentation faults and the program crashes.
The specific code section that is seg faulting is...
mutex.lock();
password = attemptList.front();
attemptList.pop_front();
size = attemptList.size();
std::cout << password << std::endl;
mutex.unlock();
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <string>
#include <iostream>
#include <chrono>
#include <shared_mutex>
#include <unistd.h>
#include <sys/ipc.h>
#include <mutex>
#include <sys/shm.h>
#include <sys/wait.h>
#include <thread>
#include <vector>
#include <algorithm>
#include <list>
#define MAX_LENGTH 4
#define MAX_QUEUE_SIZE 1000
#define CHARACTER_LIST "abcdefghijklmnopqrstuvwxyz"
void enqueue_passwords(const std::string& charList);
void bruteforce();
void do_join(std::thread& t);
void join_all(std::vector<std::thread>& v);
std::list<std::string> attemptList;
std::mutex mutex;
bool conclude = false;
int main(int argc, char* argv[]) {
auto start = std::chrono::high_resolution_clock::now();
int index;
std::vector<std::thread> threads;
for (index = 0; index < 2; index++) {
threads.emplace_back(std::thread(bruteforce));
}
enqueue_passwords(CHARACTER_LIST);
join_all(threads);
auto stop = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(stop - start);
std::cout << duration.count() << " milliseconds" << std::endl;
return 0;
}
void bruteforce() {
double size = 0;
std::string password;
while (!conclude) {
do {
mutex.lock();
size = attemptList.size();
mutex.unlock();
if (size == 0) {
usleep(300);
}
} while (size == 0);
while(size != 0) {
mutex.lock();
password = attemptList.front();
attemptList.pop_front();
size = attemptList.size();
std::cout << password << std::endl;
mutex.unlock();
}
}
}
void enqueue_passwords(const std::string& charList) {
const int maxLength = MAX_LENGTH;
const int charListLength = charList.length();
char password[MAX_LENGTH + 1];
memset(password, '\0', MAX_LENGTH + 1);
int index;
int number;
double permutations = 0;
double count = 0;
double passPosition = 0;
double size = 0;
// Calculate number of permutations possible
for (index = 0; index < maxLength; index++) {
permutations += charListLength * powl(charList.length(), maxLength - index - 1);
}
std::cout << "Permutations: " << permutations << std::endl << std::endl;
password[0] = charList[0];
while (count < permutations) {
do {
mutex.lock();
size = attemptList.size();
mutex.unlock();
if (size > MAX_QUEUE_SIZE) {
usleep(250);
}
} while (size > MAX_QUEUE_SIZE);
// Loop over current set of characters ,changing the last one
for (index = 0; index < charListLength; index++) {
password[int(passPosition)] = charList[index];
// ENQUEUE HERE //
mutex.lock();
attemptList.push_back(std::string(password));
mutex.unlock();
// ENQUEUE HERE //
if (count > permutations) {
break;
}
count++;
}
// Iterate over remaining indexes, except for the last one
for (number = int(passPosition); number >= 0; number--) {
if (password[number] != charList[charListLength - 1]) {
password[number]++;
break;
} else {
if (number == 0) {
passPosition++;
for (index = 0; index < passPosition + 1; index++) {
password[index] = charList[0];
}
break;
}
password[number] = charList[0];
}
}
}
conclude = true;
}
void do_join(std::thread& t) {
t.join();
}
void join_all(std::vector<std::thread>& v) {
std::for_each(v.begin(), v.end(), do_join);
}