diff --git a/brute/source/bruteforce.c b/brute/source/bruteforce.c index e2b7102..6d57dbe 100644 --- a/brute/source/bruteforce.c +++ b/brute/source/bruteforce.c @@ -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 #include #include @@ -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);