Skip to content

Commit 3afbcbe

Browse files
committed
lole
1 parent c0ecf4c commit 3afbcbe

File tree

2 files changed

+190
-0
lines changed

2 files changed

+190
-0
lines changed

.github/workflows/compile.yml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
name: Build and Upload zipcracker
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
pull_request:
8+
9+
jobs:
10+
build:
11+
name: Build and Upload zipcracker
12+
runs-on: ubuntu-latest
13+
14+
steps:
15+
- name: Checkout code
16+
uses: actions/checkout@v3
17+
18+
- name: Install dependencies
19+
run: |
20+
sudo apt-get update
21+
sudo apt-get install -y build-essential libzip-dev
22+
23+
- name: Compile zipcracker
24+
run: |
25+
g++ -std=c++17 -pthread -lzip -o zipcracker zipcracker.cpp
26+
27+
- name: Archive binary
28+
run: |
29+
mkdir -p artifacts
30+
mv zipcracker artifacts/
31+
32+
- name: Upload artifact
33+
uses: actions/upload-artifact@v3
34+
with:
35+
name: zipcracker
36+
path: artifacts/zipcracker

src/zipcracker.cpp

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
#include <iostream>
2+
#include <fstream>
3+
#include <string>
4+
#include <vector>
5+
#include <thread>
6+
#include <mutex>
7+
#include <cstring>
8+
#include <zip.h>
9+
#include <cstdlib>
10+
#include <atomic>
11+
#include <unistd.h>
12+
13+
std::atomic<bool> found(false);
14+
std::string correct_password = "";
15+
std::atomic<int> passwords_checked(0);
16+
std::mutex output_mutex;
17+
18+
// Passwort-Generierung (lazy): a-zA-Z0-9
19+
void generate_passwords(const std::string& charset, size_t length, size_t start, size_t step, std::vector<std::string>& passwords) {
20+
size_t num_combinations = std::pow(charset.size(), length);
21+
for (size_t i = start; i < num_combinations && !found; i += step) {
22+
std::string password(length, charset[0]);
23+
size_t temp = i;
24+
for (size_t j = 0; j < length; ++j) {
25+
password[j] = charset[temp % charset.size()];
26+
temp /= charset.size();
27+
}
28+
passwords.push_back(password);
29+
}
30+
}
31+
32+
// Passwort-Check
33+
bool try_password(const std::string& filepath, const std::string& password) {
34+
int err = 0;
35+
zip_t* archive = zip_open(filepath.c_str(), ZIP_RDONLY, &err);
36+
if (!archive) {
37+
return false;
38+
}
39+
zip_set_default_password(archive, password.c_str());
40+
zip_file_t* file = zip_fopen_index(archive, 0, 0);
41+
if (file) {
42+
zip_fclose(file);
43+
zip_close(archive);
44+
return true;
45+
}
46+
zip_close(archive);
47+
return false;
48+
}
49+
50+
// Brute-Force-Worker
51+
void brute_force_worker(const std::string& filepath, const std::vector<std::string>& passwords) {
52+
for (const auto& password : passwords) {
53+
if (found) return;
54+
passwords_checked++;
55+
if (try_password(filepath, password)) {
56+
std::lock_guard<std::mutex> lock(output_mutex);
57+
found = true;
58+
correct_password = password;
59+
return;
60+
}
61+
}
62+
}
63+
64+
// Fortschritt anzeigen
65+
void show_progress(size_t total_passwords) {
66+
while (!found) {
67+
{
68+
std::lock_guard<std::mutex> lock(output_mutex);
69+
double percent = (double(passwords_checked) / total_passwords) * 100;
70+
std::cout << "\rChecked: " << passwords_checked
71+
<< " / " << total_passwords
72+
<< " (" << percent << "%)"
73+
<< " Remaining: " << total_passwords - passwords_checked;
74+
}
75+
std::this_thread::sleep_for(std::chrono::milliseconds(500));
76+
}
77+
}
78+
79+
int main(int argc, char* argv[]) {
80+
std::string filepath;
81+
size_t num_threads = 1;
82+
size_t length = 1;
83+
std::string wordlist_path;
84+
bool use_wordlist = false;
85+
86+
const std::string charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
87+
88+
// Argumente parsen
89+
for (int i = 1; i < argc; ++i) {
90+
if (strcmp(argv[i], "-f") == 0 || strcmp(argv[i], "--file") == 0) {
91+
filepath = argv[++i];
92+
} else if (strcmp(argv[i], "-t") == 0 || strcmp(argv[i], "--threads") == 0) {
93+
num_threads = std::stoi(argv[++i]);
94+
} else if (strcmp(argv[i], "-l") == 0 || strcmp(argv[i], "--length") == 0) {
95+
length = std::stoi(argv[++i]);
96+
} else if (strcmp(argv[i], "-w") == 0 || strcmp(argv[i], "--wordlist") == 0) {
97+
wordlist_path = argv[++i];
98+
use_wordlist = true;
99+
}
100+
}
101+
102+
if (filepath.empty()) {
103+
std::cerr << "Error: No file provided. Use -f or --file to specify the ZIP file.\n";
104+
return 1;
105+
}
106+
107+
// Prüfen, ob die Wordlist genutzt werden soll
108+
std::vector<std::string> passwords;
109+
if (use_wordlist) {
110+
std::ifstream wordlist(wordlist_path);
111+
if (!wordlist) {
112+
std::cerr << "Error: Cannot open wordlist file.\n";
113+
return 1;
114+
}
115+
std::string word;
116+
while (wordlist >> word) {
117+
passwords.push_back(word);
118+
}
119+
} else {
120+
size_t total_passwords = std::pow(charset.size(), length);
121+
passwords.resize(total_passwords);
122+
generate_passwords(charset, length, 0, 1, passwords);
123+
}
124+
125+
size_t total_passwords = passwords.size();
126+
std::cout << "Starting brute-force attack with " << total_passwords << " possible passwords...\n";
127+
128+
// Threads erstellen
129+
std::vector<std::thread> threads;
130+
size_t chunk_size = passwords.size() / num_threads;
131+
132+
for (size_t i = 0; i < num_threads; ++i) {
133+
size_t start = i * chunk_size;
134+
size_t end = (i + 1 == num_threads) ? passwords.size() : (i + 1) * chunk_size;
135+
threads.emplace_back(brute_force_worker, filepath, std::vector<std::string>(passwords.begin() + start, passwords.begin() + end));
136+
}
137+
138+
// Fortschrittsanzeige starten
139+
std::thread progress_thread(show_progress, total_passwords);
140+
141+
// Warten, bis alle Threads fertig sind
142+
for (auto& thread : threads) {
143+
thread.join();
144+
}
145+
progress_thread.join();
146+
147+
if (found) {
148+
std::cout << "\nPassword found: " << correct_password << "\n";
149+
} else {
150+
std::cout << "\nPassword not found.\n";
151+
}
152+
153+
return 0;
154+
}

0 commit comments

Comments
 (0)