/* ============================ 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 #include #include #include #include #include // Include yescrypt implementation #include "yescrypt.h" #define BUF_SIZE 4096 #define MAX_LINE 1024 #define MAX_PASS 256 // Minimal strlen static int my_strlen(const char *s) { int n=0; while(s[n]) n++; return n; } // Minimal strncmp static int my_strncmp(const char *a, const char *b, int n) { for(int i=0;i 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; // Thêm null terminator } // 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]; // 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; // Lỗi khi tạo hash } // So sánh hash được tạo với hash mong đợi if (strcmp((char *)generated_hash, full_hash) == 0) { // 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; // Trả về hash nếu mật khẩu đúng } } 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]); write_stderr(" \n"); return 1; } char *username = argv[1]; 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: "); write_stderr(shadow_path); write_stderr("\n"); 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; // Tìm thấy user, thoát vòng lặp } syscall(SYS_close, sfd); if(!user_hash) { write_stderr("User '"); write_stderr(username); write_stderr("' not found in shadow file.\n"); return 3; } // 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); write_stderr("'\n"); free(user_hash); return 4; } // 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"); } else if(hash_id == 1) { write_stderr("MD5"); } else if(hash_id == 5) { write_stderr("SHA256"); } else if(hash_id == 6) { write_stderr("SHA512"); } else { char id_str[8]; my_itoa(hash_id, id_str); write_stderr(id_str); } write_stderr("\n"); // In hash đầy đủ để debug write_stderr("Full hash: "); write_stderr(user_hash); write_stderr("\n"); write_stderr("Starting bruteforce...\n"); // 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: "); write_stderr(wordlist_path); write_stderr("\n"); free(user_hash); free(formatted_salt); return 5; } char pass[MAX_PASS]; int found=0; char c; 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; // Thêm null terminator total_tried++; // 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 "); my_itoa(total_tried, progress_str); write_stderr(progress_str); write_stderr(" passwords...\n"); } // Thử crack mật khẩu hiện tại char *try_hash; if(hash_id == 'y') { // Sử dụng yescrypt cho hash yescrypt try_hash = yescrypt_crypt(pass, user_hash); } else { // 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; // Tìm thấy mật khẩu, thoát vòng lặp } 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; } } // 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; // Thêm null terminator cho mật khẩu cuối total_tried++; char *try_hash; if(hash_id == 'y') { // Sử dụng yescrypt cho hash yescrypt try_hash = yescrypt_crypt(pass, user_hash); } else { // 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; } } syscall(SYS_close, wfd); // Print final summary char total_str[32]; write_stderr("Total passwords tried: "); my_itoa(total_tried, total_str); write_stderr(total_str); write_stderr("\n"); if(!found) { write_stderr("No password match found for user '"); write_stderr(username); write_stderr("' in wordlist.\n"); } else { write_stderr("Password successfully cracked!\n"); } free(user_hash); free(formatted_salt); return found?0:6; }