Enhance bruteforce.c with detailed comments and documentation in Vietnamese, explaining the program's functionality, usage, and security notes. Improved code readability with comments on key functions and processes.

This commit is contained in:
2025-07-04 23:52:27 +00:00
parent 3b51303ab6
commit 541f9381cd

View File

@@ -1,3 +1,65 @@
/*
============================
Giải thích chi tiết về cách hoạt động của bruteforce.c
Tác giả: @tuankiet2s
Mục đích:
---------
Đây là chương trình brute-force mật khẩu người dùng trên hệ thống Unix/Linux, hỗ trợ nhiều loại hash (yescrypt, MD5, SHA256, SHA512). Chương trình được thiết kế tối giản, không phụ thuộc thư viện ngoài, tối ưu cho kích thước nhỏ nhất.
Quy trình hoạt động:
--------------------
1. Đọc tham số dòng lệnh:
- argv[1]: tên user cần brute-force
- argv[2]: đường dẫn file wordlist (danh sách mật khẩu thử)
2. Đọc file /etc/shadow:
- Mở file /etc/shadow bằng syscall để lấy dòng chứa thông tin hash của user mục tiêu.
- Nếu không tìm thấy user, thông báo lỗi và thoát.
3. Phân tích chuỗi hash:
- Hàm parse_hash() tách loại hash (hash_id), salt, và giá trị hash thực tế từ chuỗi hash lấy được.
- Hỗ trợ các định dạng: yescrypt ($y$), MD5 ($1$), SHA256 ($5$), SHA512 ($6$).
- Tạo salt phù hợp để truyền vào hàm crypt() hoặc yescrypt.
4. Đọc file wordlist và thử từng mật khẩu:
- Đọc từng dòng (mỗi dòng là một mật khẩu) từ file wordlist.
- Với mỗi mật khẩu:
+ Nếu hash_id là 'y' (yescrypt), sử dụng hàm yescrypt_crypt() để kiểm tra.
+ Nếu là hash khác, sử dụng hàm crypt() của hệ thống với salt đã tạo.
- So sánh kết quả hash với hash của user. Nếu trùng khớp, in ra mật khẩu và kết thúc.
- Cập nhật tiến trình mỗi 1000 lần thử.
5. Xử lý dòng cuối cùng nếu file không kết thúc bằng newline.
6. In thống kê cuối cùng:
- Số lượng mật khẩu đã thử
- Thông báo thành công hoặc thất bại
Các hàm phụ trợ:
----------------
- my_strlen, my_strncmp: các hàm xử lý chuỗi tối giản
- write_stderr, write_stdout: ghi ra stderr/stdout bằng syscall
- strpos: tìm vị trí chuỗi con trong chuỗi
- read_line: đọc từng dòng từ file descriptor
- extract_user_hash: lấy hash của user từ dòng shadow
- parse_hash: tách thông tin từ chuỗi hash
- create_salt: tạo salt phù hợp cho crypt()
- my_itoa: chuyển số nguyên thành chuỗi
- yescrypt_crypt: kiểm tra mật khẩu với yescrypt
Lưu ý bảo mật:
--------------
- Chỉ sử dụng cho mục đích kiểm thử hợp pháp, giáo dục.
- Không sử dụng trên hệ thống không được phép.
- Cần quyền root để truy cập /etc/shadow.
Tối ưu hóa:
-----------
- Biên dịch tĩnh, strip symbol, nén UPX để giảm kích thước binary tối đa.
- Đọc file và xử lý chuỗi bằng syscall, không dùng thư viện chuẩn để giảm dependency.
*/
#include <unistd.h>
#include <sys/syscall.h>
#include <fcntl.h>
@@ -28,19 +90,23 @@ static void write_stdout(const char *s) {
syscall(SYS_write, 1, s, my_strlen(s));
}
// Find position of substring in string
// Tìm vị trí chuỗi con trong chuỗi chính
// Thuật toán: duyệt từng vị trí trong chuỗi chính, so sánh với chuỗi con
static int strpos(const char *string, const char *substring, int offset) {
int string_len = my_strlen(string);
int sub_len = my_strlen(substring);
// Duyệt từ vị trí offset đến vị trí có thể chứa chuỗi con
for(int i = offset; i <= string_len - sub_len; i++) {
int j;
// So sánh từng ký tự của chuỗi con với chuỗi chính tại vị trí i
for(j = 0; j < sub_len; j++) {
if(string[i + j] != substring[j]) break;
}
// Nếu so sánh hết chuỗi con mà không khác biệt, đã tìm thấy
if(j == sub_len) return i;
}
return -1;
return -1; // Không tìm thấy
}
// Read a line from fd into buf, return length or 0 on EOF
@@ -57,27 +123,33 @@ static int read_line(int fd, char *buf, int max) {
return i;
}
// Extract user hash from shadow line
// Trích xuất hash của user từ dòng trong file shadow
// Format: username:hash:other_fields
static char* extract_user_hash(const char *shadow_line, const char *username) {
// Tìm vị trí username trong dòng shadow
int username_index = strpos(shadow_line, username, 0);
if(username_index == -1) return NULL;
// Find the start of hash (after username:)
// Tìm vị trí bắt đầu hash (sau username:)
int hash_start = username_index + my_strlen(username) + 1;
// Tìm vị trí kết thúc hash (dấu : tiếp theo)
int hash_end = strpos(shadow_line, ":", hash_start);
if(hash_end == -1) return NULL;
// Tính độ dài hash và cấp phát bộ nhớ
int hash_len = hash_end - hash_start;
char *user_hash = malloc(hash_len + 1);
// Copy hash từ dòng shadow vào buffer mới
memcpy(user_hash, shadow_line + hash_start, hash_len);
user_hash[hash_len] = 0;
user_hash[hash_len] = 0; // Thêm null terminator
return user_hash;
}
// Parse hash to extract algorithm ID, salt, and hash value
// Phân tích chuỗi hash để trích xuất ID thuật toán, salt, và giá trị hash
// Hỗ trợ format: $id$salt$hash hoặc $y$params$salt$hash (yescrypt)
static void parse_hash(const char *user_hash, int *hash_id, char *salt, char *hash_value) {
// Find positions of $ characters
// Tìm vị trí các ký tự $ để phân tích cấu trúc hash
int first_dollar = strpos(user_hash, "$", 0);
if(first_dollar == -1) return;
@@ -87,36 +159,36 @@ static void parse_hash(const char *user_hash, int *hash_id, char *salt, char *ha
int third_dollar = strpos(user_hash, "$", second_dollar + 1);
if(third_dollar == -1) return;
// Extract hash ID (algorithm)
// Trích xuất ID thuật toán (giữa $ đầu tiên và $ thứ hai)
int id_len = second_dollar - first_dollar - 1;
char id_str[8] = {0};
memcpy(id_str, user_hash + first_dollar + 1, id_len);
// Handle yescrypt (y) and numeric IDs
// Xử lý yescrypt (y) và các ID số
if(id_len == 1 && id_str[0] == 'y') {
*hash_id = 'y'; // yescrypt
*hash_id = 'y'; // Đánh dấu là yescrypt
// For yescrypt, we need to find the 4th $ to get the actual salt
// Với yescrypt, cần tìm $ th 4 để lấy salt thực tế
int fourth_dollar = strpos(user_hash, "$", third_dollar + 1);
if(fourth_dollar == -1) return;
// Extract parameters (between 2nd and 3rd $)
// Trích xuất tham số (giữa $ thứ 2 và $ thứ 3)
int param_len = third_dollar - second_dollar - 1;
char parameters[64] = {0};
memcpy(parameters, user_hash + second_dollar + 1, param_len);
parameters[param_len] = 0;
// Extract salt (between 3rd and 4th $)
// Trích xuất salt (giữa $ thứ 3 và $ thứ 4)
int salt_len = fourth_dollar - third_dollar - 1;
memcpy(salt, user_hash + third_dollar + 1, salt_len);
salt[salt_len] = 0;
// Extract hash value (after 4th $)
// Trích xuất giá trị hash (sau $ thứ 4)
int hash_len = my_strlen(user_hash) - fourth_dollar - 1;
memcpy(hash_value, user_hash + fourth_dollar + 1, hash_len);
hash_value[hash_len] = 0;
// For yescrypt, we need to include parameters in the salt for crypt()
// Với yescrypt, cần kết hợp tham số vào salt cho hàm crypt()
char combined_salt[128];
int len = 0;
combined_salt[len++] = '$';
@@ -129,18 +201,19 @@ static void parse_hash(const char *user_hash, int *hash_id, char *salt, char *ha
len += salt_len;
combined_salt[len] = 0;
// Copy the combined salt back to the salt parameter
// Copy salt đã kết hợp vào tham số salt
memcpy(salt, combined_salt, len + 1);
} else {
// Xử lý các thuật toán hash khác (MD5, SHA256, SHA512)
*hash_id = atoi(id_str);
// Extract salt (standard format)
// Trích xuất salt (format chuẩn)
int salt_len = third_dollar - second_dollar - 1;
memcpy(salt, user_hash + second_dollar + 1, salt_len);
salt[salt_len] = 0;
// Extract hash value
// Trích xuất giá trị hash
int hash_len = my_strlen(user_hash) - third_dollar - 1;
memcpy(hash_value, user_hash + third_dollar + 1, hash_len);
hash_value[hash_len] = 0;
@@ -181,40 +254,45 @@ static char* create_salt(int hash_id, const char *salt) {
return formatted_salt;
}
// Minimal itoa for positive integers
// Chuyển đổi số nguyên dương thành chuỗi (itoa tối giản)
// Thuật toán: chia liên tiếp cho 10, lưu các chữ số vào mảng tạm, sau đó đảo ngược
static void my_itoa(int value, char *buf) {
char tmp[16];
int i = 0, j = 0;
if (value == 0) { buf[0] = '0'; buf[1] = 0; return; }
if (value == 0) { buf[0] = '0'; buf[1] = 0; return; } // Xử lý trường hợp đặc biệt
// Chia liên tiếp cho 10, lưu từng chữ số vào mảng tạm (theo thứ tự ngược)
while (value > 0) { tmp[i++] = '0' + (value % 10); value /= 10; }
// Đảo ngược thứ tự các chữ số để có kết quả đúng
while (i > 0) { buf[j++] = tmp[--i]; }
buf[j] = 0;
buf[j] = 0; // Thêm null terminator
}
// Custom yescrypt crypt function using reference implementation parsing
// Hàm crypt tùy chỉnh cho yescrypt sử dụng implementation tham chiếu
// Mục đích: tạo hash từ mật khẩu và so sánh với hash đã biết
static char* yescrypt_crypt(const char *password, const char *full_hash) {
static char result[128];
// Use the reference implementation's yescrypt function
// Sử dụng hàm yescrypt từ implementation tham chiếu để tạo hash
uint8_t *generated_hash = yescrypt((const uint8_t *)password, (const uint8_t *)full_hash);
if (!generated_hash) {
return NULL;
return NULL; // Lỗi khi tạo hash
}
// Compare the generated hash with the expected hash
// So sánh hash được tạo với hash mong đợi
if (strcmp((char *)generated_hash, full_hash) == 0) {
// Copy the generated hash to our result buffer
// Nếu trùng khớp, copy hash vào buffer kết quả
int len = strlen((char *)generated_hash);
if (len < sizeof(result)) {
memcpy(result, generated_hash, len + 1);
return result;
return result; // Trả về hash nếu mật khẩu đúng
}
}
return NULL;
return NULL; // Mật khẩu không đúng
}
int main(int argc, char **argv) {
// Kiểm tra tham số dòng lệnh
if(argc<3) {
write_stderr("Usage: ");
write_stderr(argv[0]);
@@ -225,6 +303,7 @@ int main(int argc, char **argv) {
char *wordlist_path = argv[2];
const char *shadow_path = "/etc/shadow";
// Mở file /etc/shadow để đọc thông tin hash của user
int sfd = syscall(SYS_open, shadow_path, O_RDONLY, 0);
if(sfd<0) {
write_stderr("Failed to open shadow file: ");
@@ -233,11 +312,12 @@ int main(int argc, char **argv) {
return 2;
}
// Đọc từng dòng trong file shadow, tìm dòng chứa thông tin user mục tiêu
char line[MAX_LINE];
char *user_hash = NULL;
while(read_line(sfd, line, MAX_LINE)) {
user_hash = extract_user_hash(line, username);
if(user_hash) break;
if(user_hash) break; // Tìm thấy user, thoát vòng lặp
}
syscall(SYS_close, sfd);
@@ -248,12 +328,13 @@ int main(int argc, char **argv) {
return 3;
}
// Parse the hash
// Phân tích chuỗi hash để lấy thông tin thuật toán, salt, và giá trị hash
int hash_id;
char salt[64] = {0};
char hash_value[512] = {0};
parse_hash(user_hash, &hash_id, salt, hash_value);
// Kiểm tra xem có phân tích được hash không
if(hash_id == 0) {
write_stderr("Failed to parse hash format for user '");
write_stderr(username);
@@ -262,11 +343,12 @@ int main(int argc, char **argv) {
return 4;
}
// Print useful information
// In thông tin hữu ích về target và thuật toán hash
write_stderr("Target user: ");
write_stderr(username);
write_stderr("\n");
// Xác định và in loại hash algorithm
write_stderr("Hash type: ");
if(hash_id == 'y') {
write_stderr("yescrypt");
@@ -283,15 +365,17 @@ int main(int argc, char **argv) {
}
write_stderr("\n");
// In hash đầy đủ để debug
write_stderr("Full hash: ");
write_stderr(user_hash);
write_stderr("\n");
write_stderr("Starting bruteforce...\n");
// Create formatted salt for crypt()
// Tạo salt đã format cho hàm crypt() (cần thiết cho các hash không phải yescrypt)
char *formatted_salt = create_salt(hash_id, salt);
// Mở file wordlist để đọc danh sách mật khẩu cần thử
int wfd = syscall(SYS_open, wordlist_path, O_RDONLY, 0);
if(wfd<0) {
write_stderr("Failed to open wordlist: ");
@@ -308,13 +392,15 @@ int main(int argc, char **argv) {
int n=0;
int total_tried=0;
// Vòng lặp chính: đọc từng ký tự từ wordlist, xây dựng từng mật khẩu
while(syscall(SYS_read, wfd, &c, 1) == 1) {
if(c == '\n' || c == '\r') {
// Gặp kết thúc dòng, xử lý mật khẩu đã đọc
if(n > 0) {
pass[n] = 0;
pass[n] = 0; // Thêm null terminator
total_tried++;
// Show progress every 1000 attempts
// Hiển thị tiến trình mỗi 1000 lần thử
if(total_tried % 1000 == 0) {
char progress_str[32];
write_stderr("Tried ");
@@ -323,44 +409,48 @@ int main(int argc, char **argv) {
write_stderr(" passwords...\n");
}
// Thử crack mật khẩu hiện tại
char *try_hash;
if(hash_id == 'y') {
// Use yescrypt for yescrypt hashes
// Sử dụng yescrypt cho hash yescrypt
try_hash = yescrypt_crypt(pass, user_hash);
} else {
// Use system crypt() for other hash types
// Sử dụng crypt() của hệ thống cho các loại hash khác
try_hash = crypt(pass, formatted_salt);
}
// So sánh hash được tạo với hash gốc
if(try_hash && strcmp(try_hash, user_hash)==0) {
write_stdout("Found password: ");
write_stdout(pass);
write_stdout("\n");
found=1;
break;
break; // Tìm thấy mật khẩu, thoát vòng lặp
}
n = 0;
n = 0; // Reset để đọc mật khẩu tiếp theo
}
} else if(n < MAX_PASS-1) {
// Thêm ký tự vào buffer mật khẩu hiện tại
pass[n++] = c;
}
}
// Handle last line if no newline at end
// Xử lý dòng cuối cùng nếu file không kết thúc bằng newline
if(n > 0 && !found) {
pass[n] = 0;
pass[n] = 0; // Thêm null terminator cho mật khẩu cuối
total_tried++;
char *try_hash;
if(hash_id == 'y') {
// Use yescrypt for yescrypt hashes
// Sử dụng yescrypt cho hash yescrypt
try_hash = yescrypt_crypt(pass, user_hash);
} else {
// Use system crypt() for other hash types
// Sử dụng crypt() của hệ thống cho các loại hash khác
try_hash = crypt(pass, formatted_salt);
}
// So sánh hash được tạo với hash gốc
if(try_hash && strcmp(try_hash, user_hash)==0) {
write_stdout("Found password: ");
write_stdout(pass);