Các nhà phát triển tạo hệ thống đăng nhập biết rõ hơn là lưu trữ mật khẩu ở dạng văn bản thuần túy, thường lưu trữ hàm băm của mật khẩu để ngăn việc lưu trữ thông tin đăng nhập theo cách mà tin tặc có thể đánh cắp. Do cách hoạt động của hàm băm, không phải tất cả đều được tạo ra như nhau. Một số dễ bị tổn thương hơn những cái khác và một chút Python có thể được sử dụng để bắt buộc bất kỳ hàm băm yếu nào để lấy mật khẩu mà chúng được tạo từ đó
Một chút về băm
Tin tặc thường đánh cắp toàn bộ cơ sở dữ liệu về dữ liệu đăng nhập và mật khẩu của người dùng và do đó, hàm băm là cách ưa thích để lưu trữ thông tin nhạy cảm như mật khẩu
Băm khác với mã hóa vì chúng không lưu trữ dữ liệu. Thay vào đó, con số tạo nên hàm băm là kết quả của phép tính chạy trên bất cứ thứ gì bạn đang băm, có thể là mật khẩu hoặc toàn bộ tệp. Điều này được sử dụng để đảm bảo rằng tệp bạn đang tải xuống khớp với tệp bạn định tải xuống hoặc để xác nhận mật khẩu mà người dùng đã nhập khớp với mật khẩu họ đã đăng ký
Tùy thuộc vào kích thước của tệp hoặc mật khẩu mà bạn đang băm, các hàm băm như SHA-1 hoặc MD5 sẽ lấy các khối dữ liệu cố định mà bạn đang băm và chạy một phép tính phức tạp trên từng khối cho đến khi đạt đến giá trị cuối cùng. Giá trị này là một số rất dài được thiết kế là duy nhất để người ta có thể xác minh rằng một tệp khớp với tệp khác bằng cách so sánh các giá trị băm. Nếu giá trị băm khác, thì một cái gì đó về tệp đã bị thay đổi
Điều này thật tuyệt vì nếu người dùng nhập bất kỳ mật khẩu nào khác với mật khẩu họ đã chọn, giá trị băm sẽ hoàn toàn khác. Do đó, nhà phát triển chỉ cần lưu trữ hàm băm, bởi vì bất cứ lúc nào người dùng cần đăng nhập, họ có thể chỉ cần nhập mật khẩu để tạo hàm băm mới để so sánh với hàm băm đã lưu trữ
Ví dụ: tôi đã băm nullbyte thành giá trị SHA-1 sau. Bạn có thể tạo hàm băm SHA-1 của riêng mình tại sha1-online. com để tự mình xem nó trông như thế nào
32c0ced56f1fe08583bdb079d85a35a81995018c
Một vấn đề với Băm SHA-1
Thật không may cho các nhà phát triển, không phải tất cả các giá trị băm đều được tạo ra như nhau để lưu trữ mật khẩu. Đối với các hàm băm như SHA-1, có một số vấn đề khiến việc lưu mật khẩu bằng SHA-1 trở thành một giải pháp kém lý tưởng
Để làm nổi bật một từ, mỗi khi bạn băm cùng một từ với SHA-1, nó sẽ tạo ra cùng một hàm băm. Mặc dù điều này là do thiết kế, nhưng bạn có thể chỉ cần thực hiện một số lượng lớn các lần đoán và băm tất cả chúng vào SHA-1, sau đó nhanh chóng so sánh các giá trị băm để lấy mật khẩu mà hàm băm SHA-1 được lấy từ đó. Vì SHA-1 được thiết kế để có tốc độ nhanh, nên quá trình này mất một khoảng thời gian rất ngắn, điều này khiến cho việc sử dụng vũ phu trở nên dễ dàng hơn
Có một số giải pháp cho vấn đề này và một trong những giải pháp phổ biến nhất là thêm muối. Muối là một chuỗi văn bản mà bạn có thể thêm vào mật khẩu trước khi băm nó. Một ví dụ sẽ là thêm từ muối vào nullbyte mật khẩu. Mặc dù chúng tôi biết giá trị SHA-1 của nullbyte ở trên, hàm băm của nullbytesalt hoặc saltnullbyte sẽ hoàn toàn khác. Điều này hữu ích, nhưng nếu muối không phù hợp với mỗi người dùng, thì việc tìm ra muối không quá khó và bạn sẽ quay lại vấn đề tương tự
Bcrypt có thể giúp băm an toàn hơn như thế nào
Một giải pháp tốt hơn là thêm một loại muối ngẫu nhiên và có một thuật toán băm được tạo để lưu trữ mật khẩu với chính xác điều này
Bcrypt không chỉ cố tình làm chậm quá trình cưỡng bức vũ phu mà còn thêm một loại muối ngẫu nhiên vào mỗi hàm băm mà nó tạo ra. Do đó, không có hai mã băm bcrypt nào giống nhau, ngay cả khi chúng được tạo từ cùng một mật khẩu. Để kiểm tra dự đoán đối với hàm băm bcrypt, thay vào đó, bạn phải sử dụng hàm bcrypt lấy dự đoán mật khẩu và hàm băm làm đối số và trả về kết quả xem chúng có khớp hay không
Để thể hiện cách hoạt động của các hàm băm khác nhau này, tôi đã viết một số Python để biến bất kỳ mật khẩu nào thành hàm băm SHA-1, MD5 và bcrypt
import hashlib, bcrypt
#Demonstrates the difference between two types of hashing, SHA1 and Bcrypt
password = input["Input the password to hash\n>"]
print["\nSHA1:\n"]
for i in range[3]:
setpass = bytes[password, 'utf-8']
hash_object = hashlib.sha1[setpass]
guess_pw = hash_object.hexdigest[]
print[guess_pw]
print["\nMD5:\n"]
for i in range[3]:
setpass = bytes[password, 'utf-8']
hash_object = hashlib.md5[setpass]
guess_pw = hash_object.hexdigest[]
print[guess_pw]
print["\nBCRYPT:\n"]
for i in range[3]:
hashed = bcrypt.hashpw[setpass, bcrypt.gensalt[10]]
Như bạn có thể thấy bên dưới, các mã băm MD5 và SHA-1 đều giống hệt nhau, nhưng các mã băm bcrypt thay đổi mỗi khi chúng được tạo. Đối với các nhà phát triển, bcrypt rõ ràng là lựa chọn tốt hơn. Nhưng nếu chúng tôi tình cờ gặp cơ sở dữ liệu mật khẩu băm SHA-1 hoặc MD5, thì làm cách nào chúng tôi thực sự có thể bắt buộc sử dụng hàm băm?
/Users/skickar/venv/untitled10/bin/python /Users/skickar/Desktop/TestSHA1.py
Input the password to hash
>nullbyte
SHA1:
32c0ced56f1fe08583bdb079d85a35a81995018c
32c0ced56f1fe08583bdb079d85a35a81995018c
32c0ced56f1fe08583bdb079d85a35a81995018c
MD5:
5f804b61f8dcf70044ad8c1385e946a8
5f804b61f8dcf70044ad8c1385e946a8
5f804b61f8dcf70044ad8c1385e946a8
BCRYPT:
b'$2b$10$Z1WVDUi50fmqyrpw19rIyOLPIKVUFeh7HO0FfQi1MbKjyxyduG2WS'
b'$2b$10$F.vehMYSUh/6zmTR/VY2quTnPfzPDcIdHTfZpb8twqjRIIIEFcbUW'
b'$2b$10$pZyptPPDHrnIgpU7wTW2nu4cfGAUS65kcGZb6FMC7KmYwJmuwSoLO'
Xây dựng chương trình Python3 để Brute-Force SHA-1
Một phần của việc trưởng thành với tư cách là một hacker là học cách viết các công cụ của riêng bạn. Lúc đầu, các công cụ của bạn sẽ đơn giản và giải quyết được các vấn đề nhỏ, nhưng khi bạn tích lũy được kinh nghiệm, bạn sẽ có thể đạt được nhiều thành tựu hơn nữa. Khi bạn mới bắt đầu, các ngôn ngữ lập trình như C++ được gõ mạnh có thể khiến người mới bắt đầu khó hiểu, nhưng Python3 là ngôn ngữ linh hoạt và thân thiện với người mới bắt đầu, cho phép chúng tôi trừu tượng hóa ý tưởng và xây dựng nguyên mẫu một cách dễ dàng
Chương trình đơn giản mà chúng ta sẽ viết hôm nay sẽ giúp thực hành cách hacker tạo ra một công cụ để khai thác lỗ hổng. Trong ví dụ này, SHA-1 dễ bị tấn công bởi vì bạn có thể so sánh hai giá trị băm với nhau, vì vậy chúng tôi sẽ viết một chương trình để thực hiện chính xác điều đó
Để viết bất kỳ chương trình nào, bạn sẽ cần viết ra các bước mà chương trình của bạn cần tuân theo để thành công. Danh sách này có vẻ hơi dài, nhưng nó có thể được cô đọng và bạn nên càng cụ thể càng tốt về cách mọi thứ cần hoạt động để đạt được kết quả mong muốn. Tôi thích sử dụng bảng trắng hoặc trình tạo lưu đồ trực tuyến như MindMupp để vẽ cách các chương trình này sẽ diễn ra từ đầu đến cuối
Khi bạn đã sắp xếp các bước của mình, bạn có thể bắt đầu chuyển sang mã giả, đó là nơi bạn sắp xếp các bước theo thứ tự theo cách có thể đọc được nhưng tiến gần hơn đến cách mã thực sự được thể hiện. Với mã giả này được viết, bạn có thể bắt đầu điền từng dòng mã của mình, sửa lỗi khi chúng xảy ra và xem từng bước trong chương trình của bạn bắt đầu hình thành và tương tác với nhau
Những gì bạn sẽ cần để tiếp tục
Để làm theo hướng dẫn này, bạn sẽ cần một máy tính có Python3 để làm việc. Python3 có một số điểm khác biệt so với phiên bản Python trước đó, vì vậy bạn nên đảm bảo chọn đúng phiên bản. Bạn có thể cài đặt Python3 theo một số cách. Trong Linux, bạn có thể gõ lệnh sau để cài đặt Python3
apt install python3
Bạn sẽ cần một Python3 IDE [môi trường phát triển tích hợp]. Đây là những chương trình sẽ giúp bạn viết, kiểm tra và thử nghiệm mã của mình. Đặc biệt, tôi khuyên dùng PyCharm từ Jetbrains. Ngoài ra, phiên bản chuyên nghiệp được cung cấp miễn phí cho sinh viên, điều này hoàn toàn xứng đáng nếu bạn đủ điều kiện
- đừng bỏ lỡ. Các nguyên tắc và công nghệ cần thiết để bẻ khóa mật khẩu
Để mọi thứ hoạt động bình thường, chúng tôi sẽ cần nhập một số thư viện. Chúng tôi sẽ sử dụng các thư viện urllib, urlopen và hashlib cho mã này để có thể mở các tệp từ một URL từ xa và đoán mật khẩu băm vào SHA-1. Để bao gồm chúng, hãy tạo một tệp Python3 mới trong IDE của bạn và nhập dòng sau vào dòng đầu tiên
from urllib.request import urlopen, hashlib
Điều này sẽ nhập các thư viện cần thiết, đảm bảo phần còn lại của chương trình có quyền truy cập vào các thư viện này. Nếu bạn cần cài đặt bất kỳ thư viện nào trong số này trên máy tính của mình để chạy tập lệnh này, bạn thường có thể làm như vậy với cài đặt pip và sau đó là tên của thư viện bạn cần
Để làm theo, bạn có thể tải xuống các chương trình Python mà tôi đã viết cho ví dụ này. Để làm như vậy, hãy mở một cửa sổ đầu cuối và nhập ba lệnh sau để tải xuống các tập lệnh, thay đổi thư mục của nó và liệt kê các tệp trong đó
git clone //gitlab.com/skickar/SHA1cracker
cd SHA1cracker
ls
Bước 1. Nhận SHA-1 Hash từ người dùng
Đối với lệnh đầu tiên, chúng tôi sẽ cần lấy hàm băm mà chúng tôi muốn bẻ khóa từ người dùng. Để làm điều này, chúng ta có thể sử dụng chức năng nhập liệu, chức năng này sẽ hiển thị lời nhắc cho người dùng và cho phép họ nhập phản hồi
Trong Python, chúng ta có thể lưu trữ phản hồi này trong một biến mà không cần làm gì trước. Điều này là do Python không giống như C++, yêu cầu bạn phải khai báo mọi thứ ngay từ đầu. Chúng tôi chỉ có thể tạo các biến để giữ dữ liệu mà chúng tôi muốn khi chúng tôi di chuyển
Chúng tôi sẽ đặt tên cho biến của chúng tôi là sha1hash vì chúng tôi sẽ lưu trữ một hàm băm SHA-1 bên trong nó. Chúng tôi chỉ có thể nhập nó để tạo biến, sau đó chúng tôi sẽ cần chỉ định phản hồi của người dùng để điền vào biến đó. Trong Python, ký hiệu bằng [=] không có nghĩa là nó đang so sánh một cái gì đó để xem nó có bằng nhau không. Điều đó thực sự được thực hiện với hai dấu bằng [==] thay vào đó. Biểu tượng bằng giống như một lệnh trong Python, biến ở bên trái đang được gán dữ liệu ở bên phải của dấu bằng
Chúng tôi sẽ chỉ định bất kỳ loại nào người dùng nhập, vì vậy chúng tôi sẽ gọi hàm nhập, hàm này cũng cho phép chúng tôi đặt văn bản xuất hiện cho người dùng bên trong hai dấu ngoặc đơn. Để nói với Python rằng chúng tôi muốn in một chuỗi hoặc một tập hợp các ký tự, chúng tôi cũng sẽ đặt bất kỳ thứ gì chúng tôi đang nhập trong dấu ngoặc kép. Kết quả cuối cùng sẽ giống như thế này
sha1hash = input["Please input the hash to crack.\n>"]
Khi chúng tôi chạy cái này, một lời nhắc sẽ xuất hiện với nội dung "Vui lòng nhập hàm băm để bẻ khóa. " Sau đó, chúng tôi thấy biểu tượng "dòng mới", là dấu gạch chéo ngược [\] và n. Điều này có nghĩa là để chuyển sang một dòng mới. Cuối cùng, tôi đặt một biểu tượng > để người dùng có thể nhập phản hồi của họ trên một dòng mới. Khi chúng tôi chạy tệp, NBspecial. py, kết quả trông như thế này
Dell:SHA1cracker skickar$
Dell:SHA1cracker skickar$ python3 NBspecial.py
Please input the hash to crack
>_
Sau khi người dùng nhập một hàm băm, nó sẽ được lưu trong biến sha1hash để sử dụng sau này trong chương trình
Bước 2. Mở một tệp chứa đầy các lần đoán mật khẩu
Tiếp theo, chúng tôi muốn mở một danh sách nhiều mật khẩu phổ biến. Chúng tôi sẽ sử dụng danh sách 10.000 mật khẩu phổ biến nhất cho ví dụ của chúng tôi, đây là một tệp văn bản thuần túy được lưu trữ trên GitHub. Bạn có thể sử dụng các danh sách khác, chẳng hạn như mật khẩu bị rò rỉ trực tuyến hoặc danh sách được tạo bằng Mentalist hoặc Crunch
- đừng bỏ lỡ. Sử dụng cơ sở dữ liệu mật khẩu bị rò rỉ để tạo danh sách từ Brute-Force
Đối với tệp chúng tôi đang sử dụng, chúng tôi sẽ gán lại nó cho một biến, lần này được gọi là LIST_OF_COMMON_PASSWORDS. Để mở tệp, chúng tôi sẽ sử dụng một chức năng gọi là urlopen, cho phép chúng tôi dễ dàng mở tệp văn bản này và cho Python biết loại mã hóa chính xác. Sử dụng định dạng bên dưới
________số 8Điều này sẽ mở URL được đặt trong dấu ngoặc kép với phương thức đọc, nghĩa là chúng tôi muốn đọc văn bản từ tệp. Để đảm bảo hàm str[] biết nó đang làm việc với cái gì, chúng ta cũng sẽ thêm một lệnh và 'utf-8' sau hàm này để cho chương trình biết chúng ta đang sử dụng mã hóa văn bản UTF-8
Một lần nữa, chúng ta sẽ lưu dữ liệu dưới dạng một chuỗi và để ngăn ngừa bất kỳ sự cố nào khi thực hiện việc này, chúng ta có thể đảm bảo dữ liệu mà chúng ta đang đưa vào biến là một chuỗi bằng cách "truyền" nó thành một chuỗi trước tiên. Điều này có nghĩa là cố gắng thay đổi dữ liệu sang loại khác và có thể thực hiện chuyển đổi số nguyên thành chuỗi, chuỗi thành byte và bất kỳ loại dữ liệu nào khác mà bạn muốn. Để làm điều này, chúng tôi sẽ nhập str[] và sau đó bao gồm dữ liệu mà chúng tôi muốn chuyển thành một chuỗi bên trong dấu ngoặc đơn. Kết quả cuối cùng sẽ giống như dưới đây
LIST_OF_COMMON_PASSWORDS = str[urlopen['//raw.githubusercontent.com/danielmiessler/SecLists/master/Passwords/Common-Credentials/10-million-password-list-top-10000.txt'].read[], 'utf-8']
Trong dòng này, chúng tôi mở tệp văn bản mà chúng tôi đã chọn từ một URL từ xa, mã hóa nó dưới dạng tệp văn bản UTF-8, sau đó lưu dữ liệu đó vào một chuỗi có tên LIST_OF_COMMON_PASSWORDS
Bước 3. Hãy Đoán từ Danh sách Mật khẩu
Bây giờ, chúng ta sẽ cần giải một bài toán thú vị. Mặc dù chúng tôi biết có 10.000 mật khẩu trong tệp văn bản, nhưng chương trình không biết có bao nhiêu mật khẩu, vì vậy chúng tôi sẽ cần tạo một số mã để chạy một lần cho mỗi lần đoán trong tệp mật khẩu
- đừng bỏ lỡ. Cách phát triển một chiến lược bẻ khóa mật khẩu tốt]
Để làm điều này, chúng ta sẽ sử dụng một cấu trúc gọi là vòng lặp for. Vòng lặp for là một khái niệm rất cơ bản trong lập trình và trông giống như thế này
import hashlib, bcrypt
#Demonstrates the difference between two types of hashing, SHA1 and Bcrypt
password = input["Input the password to hash\n>"]
print["\nSHA1:\n"]
for i in range[3]:
setpass = bytes[password, 'utf-8']
hash_object = hashlib.sha1[setpass]
guess_pw = hash_object.hexdigest[]
print[guess_pw]
print["\nMD5:\n"]
for i in range[3]:
setpass = bytes[password, 'utf-8']
hash_object = hashlib.md5[setpass]
guess_pw = hash_object.hexdigest[]
print[guess_pw]
print["\nBCRYPT:\n"]
for i in range[3]:
hashed = bcrypt.hashpw[setpass, bcrypt.gensalt[10]]
0Điều này có nghĩa là đối với số lần đoán trong biến mà chúng tôi đã tạo để giữ tất cả các lần đoán trong bước cuối cùng [trong trường hợp này là 10.000], chúng tôi sẽ thực hiện hành động sau. Trong thực tế, điều này có nghĩa là chúng tôi sẽ lấy một dự đoán từ danh sách các dự đoán, thực hiện bất kỳ hành động nào và sau đó quay lại để lấy dự đoán tiếp theo cho đến khi chúng tôi hết các dự đoán mới để thử
Chúng ta có thể đặt tên cho biến chứa mỗi lần đoán bất cứ điều gì chúng ta muốn, nhưng để rõ ràng, tôi đặt tên cho nó là đoán. Chỉ cần nói cho x trong LIST_OF_COMMON_PASSWORDS cũng được
Vấn đề cuối cùng chúng ta cần giải quyết là cho chương trình biết cách chia nhỏ danh sách mật khẩu dài lớn thành các lần đoán mật khẩu riêng lẻ. Danh sách mật khẩu chúng tôi đang sử dụng phân tách mật khẩu bằng một dòng mới, vì vậy chúng tôi có thể sử dụng ký tự dòng mới để chia LIST_OF_COMMON_PASSWORDS thành các lần đoán riêng lẻ
Để thực hiện điều này, chúng ta có thể thêm. split[] vào cuối biến LIST_OF_COMMON_PASSWORDS và đặt mã cho một dòng mới [là '\n'] vào trong ngoặc đơn. Kết quả cuối cùng trông giống như dưới đây
import hashlib, bcrypt
#Demonstrates the difference between two types of hashing, SHA1 and Bcrypt
password = input["Input the password to hash\n>"]
print["\nSHA1:\n"]
for i in range[3]:
setpass = bytes[password, 'utf-8']
hash_object = hashlib.sha1[setpass]
guess_pw = hash_object.hexdigest[]
print[guess_pw]
print["\nMD5:\n"]
for i in range[3]:
setpass = bytes[password, 'utf-8']
hash_object = hashlib.md5[setpass]
guess_pw = hash_object.hexdigest[]
print[guess_pw]
print["\nBCRYPT:\n"]
for i in range[3]:
hashed = bcrypt.hashpw[setpass, bcrypt.gensalt[10]]
1Mã này sẽ lấy mật khẩu, dừng ở cuối dòng, từ biến LIST_OF_COMMON_PASSWORDS mà chúng ta đã tạo trước đó. Nó sẽ chạy bao nhiêu lần tùy theo mật khẩu trong danh sách, trừ khi chúng tôi yêu cầu nó hoạt động khác đi trong các bước tiếp theo
Bước 4. Băm dự đoán chúng tôi đã lấy từ danh sách mật khẩu
Ở đây, chúng ta sẽ cần tạo một biến mới để giữ phiên bản băm của mật khẩu đoán mà chúng ta đã lấy từ danh sách. Khi chúng tôi làm điều này, nó sẽ tạo ra một hàm băm giống hệt nhau nếu chúng tôi sử dụng cùng một mật khẩu đã được sử dụng để tạo hàm băm do người dùng cung cấp trong bước đầu tiên. Nếu trùng khớp trong bước tiếp theo, chúng tôi sẽ biết mình đã tìm thấy mật khẩu
Chúng tôi sẽ đặt tên cho biến để giữ phiên bản băm của hàm đoán hashGuess. Tiếp theo, chúng tôi sẽ cần thực hiện một số công việc chuẩn bị trước khi có thể băm dự đoán mà chúng tôi đã lấy từ danh sách mật khẩu. Để truyền biến chuỗi, chúng tôi đã gọi đoán thành đối tượng byte. Điều này là cần thiết vì hàm SHA-1 chỉ hoạt động trên các đối tượng byte, không phải chuỗi
May mắn thay, thật dễ dàng để chuyển một chuỗi thành byte. Chúng ta có thể làm điều này giống như cách chung mà chúng ta chuyển đầu vào của người dùng trong bước đầu tiên thành một chuỗi. Công thức trông giống như sau. Trong trường hợp này, chúng tôi sẽ chuyển phỏng đoán thành byte và mã hóa văn bản là UTF-8
import hashlib, bcrypt
#Demonstrates the difference between two types of hashing, SHA1 and Bcrypt
password = input["Input the password to hash\n>"]
print["\nSHA1:\n"]
for i in range[3]:
setpass = bytes[password, 'utf-8']
hash_object = hashlib.sha1[setpass]
guess_pw = hash_object.hexdigest[]
print[guess_pw]
print["\nMD5:\n"]
for i in range[3]:
setpass = bytes[password, 'utf-8']
hash_object = hashlib.md5[setpass]
guess_pw = hash_object.hexdigest[]
print[guess_pw]
print["\nBCRYPT:\n"]
for i in range[3]:
hashed = bcrypt.hashpw[setpass, bcrypt.gensalt[10]]
2Bây giờ chúng ta có phiên bản dự đoán byte, chúng ta có thể biến nó thành hàm băm SHA-1 bằng cách sử dụng đoạn mã sau
import hashlib, bcrypt
#Demonstrates the difference between two types of hashing, SHA1 and Bcrypt
password = input["Input the password to hash\n>"]
print["\nSHA1:\n"]
for i in range[3]:
setpass = bytes[password, 'utf-8']
hash_object = hashlib.sha1[setpass]
guess_pw = hash_object.hexdigest[]
print[guess_pw]
print["\nMD5:\n"]
for i in range[3]:
setpass = bytes[password, 'utf-8']
hash_object = hashlib.md5[setpass]
guess_pw = hash_object.hexdigest[]
print[guess_pw]
print["\nBCRYPT:\n"]
for i in range[3]:
hashed = bcrypt.hashpw[setpass, bcrypt.gensalt[10]]
3Vì vậy, điều này đang làm gì? . Do cách thức hoạt động của SHA-1, chúng tôi có thể tiếp tục thêm nội dung vào nó, nhưng để in giá trị hiện tại của hàm băm SHA-1, chúng tôi thêm. hexidigest[] đến hết
Trong mã cuối cùng, chúng tôi sẽ gán giá trị của dự đoán được băm cho biến HashedGuess
import hashlib, bcrypt
#Demonstrates the difference between two types of hashing, SHA1 and Bcrypt
password = input["Input the password to hash\n>"]
print["\nSHA1:\n"]
for i in range[3]:
setpass = bytes[password, 'utf-8']
hash_object = hashlib.sha1[setpass]
guess_pw = hash_object.hexdigest[]
print[guess_pw]
print["\nMD5:\n"]
for i in range[3]:
setpass = bytes[password, 'utf-8']
hash_object = hashlib.md5[setpass]
guess_pw = hash_object.hexdigest[]
print[guess_pw]
print["\nBCRYPT:\n"]
for i in range[3]:
hashed = bcrypt.hashpw[setpass, bcrypt.gensalt[10]]
4Bây giờ chúng tôi đã lưu dự đoán mật khẩu dưới dạng hàm băm, chúng tôi có thể so sánh dự đoán này với hàm băm SHA-1 ban đầu để bẻ khóa trực tiếp
Bước 5. So sánh mật khẩu được băm với hàm băm ban đầu
Trong bước này, chúng ta sẽ cần cho chương trình biết phải làm gì nếu hàm băm khớp với. Để làm điều này, chúng ta sẽ sử dụng một câu lệnh đơn giản gọi là câu lệnh if
Câu lệnh if hoạt động giống như câu lệnh for, nhưng kiểm tra một điều kiện để xem điều kiện đó có đúng hay không trước khi thực hiện phần tiếp theo của mã. Nếu điều kiện là đúng, bạn có thể yêu cầu chương trình thực hiện một hành động và nếu điều kiện đó sai, hãy thực hiện một hành động khác để thay thế
Công thức chung cho câu lệnh if trong Python như sau
import hashlib, bcrypt
#Demonstrates the difference between two types of hashing, SHA1 and Bcrypt
password = input["Input the password to hash\n>"]
print["\nSHA1:\n"]
for i in range[3]:
setpass = bytes[password, 'utf-8']
hash_object = hashlib.sha1[setpass]
guess_pw = hash_object.hexdigest[]
print[guess_pw]
print["\nMD5:\n"]
for i in range[3]:
setpass = bytes[password, 'utf-8']
hash_object = hashlib.md5[setpass]
guess_pw = hash_object.hexdigest[]
print[guess_pw]
print["\nBCRYPT:\n"]
for i in range[3]:
hashed = bcrypt.hashpw[setpass, bcrypt.gensalt[10]]
5Đối với trường hợp sử dụng của chúng tôi, chúng tôi muốn xác định xem dự đoán được băm có khớp với hàm băm ban đầu mà người dùng đã cung cấp cho chúng tôi hay không, vì vậy chúng tôi có thể sử dụng dấu == để xác định xem chúng có bằng nhau không. Câu lệnh chúng tôi muốn đánh giá là liệu hashesGuess có bằng sha1hash hay không, biến mà chúng tôi đang giữ hàm băm ban đầu. Trong mã của chúng tôi, đó là một tuyên bố đơn giản
import hashlib, bcrypt
#Demonstrates the difference between two types of hashing, SHA1 and Bcrypt
password = input["Input the password to hash\n>"]
print["\nSHA1:\n"]
for i in range[3]:
setpass = bytes[password, 'utf-8']
hash_object = hashlib.sha1[setpass]
guess_pw = hash_object.hexdigest[]
print[guess_pw]
print["\nMD5:\n"]
for i in range[3]:
setpass = bytes[password, 'utf-8']
hash_object = hashlib.md5[setpass]
guess_pw = hash_object.hexdigest[]
print[guess_pw]
print["\nBCRYPT:\n"]
for i in range[3]:
hashed = bcrypt.hashpw[setpass, bcrypt.gensalt[10]]
6Bây giờ chúng tôi đã thiết lập so sánh này, chúng tôi sẽ phải giải thích cho chương trình phải làm gì trong ba tình huống mà chúng tôi mong đợi. trùng khớp, không trùng khớp hoặc không còn mật khẩu nào trong danh sách để đoán
Bước 6. Đặt logic có điều kiện
Trong bước này, chúng tôi sẽ giải thích những việc cần làm nếu giá trị băm khớp hoặc không khớp. Bởi vì câu lệnh trước hỏi phải làm gì nếu hai cái này bằng nhau, hướng dẫn đầu tiên của chúng tôi sẽ là phải làm gì nếu hàm băm của mật khẩu đoán khớp với mật khẩu ban đầu
Nếu đây là trường hợp, chúng tôi đã tìm thấy mật khẩu và điều đúng đắn cần làm là in ra đúng mật khẩu và thoát khỏi chương trình. Nếu chúng tôi không thoát, vòng lặp sẽ tiếp tục mặc dù chúng tôi đã tìm thấy mật khẩu khớp với hàm băm SHA-1. Để làm như vậy, chúng ta chỉ cần gõ như sau
import hashlib, bcrypt
#Demonstrates the difference between two types of hashing, SHA1 and Bcrypt
password = input["Input the password to hash\n>"]
print["\nSHA1:\n"]
for i in range[3]:
setpass = bytes[password, 'utf-8']
hash_object = hashlib.sha1[setpass]
guess_pw = hash_object.hexdigest[]
print[guess_pw]
print["\nMD5:\n"]
for i in range[3]:
setpass = bytes[password, 'utf-8']
hash_object = hashlib.md5[setpass]
guess_pw = hash_object.hexdigest[]
print[guess_pw]
print["\nBCRYPT:\n"]
for i in range[3]:
hashed = bcrypt.hashpw[setpass, bcrypt.gensalt[10]]
7Điều này in mọi thứ trong dấu ngoặc kép, sau đó thêm phiên bản chuỗi của mật khẩu hiện tại đã được đoán thành công. Điều quan trọng là chúng tôi đang in biến đoán chứ không phải biến hashGuess, vì phiên bản hashGuess sẽ chỉ cung cấp cho chúng tôi một hàm băm SHA-1 khác. Trong trường hợp này, chúng tôi cũng truyền biến đó thành một chuỗi để Python có thể in nó một cách đẹp mắt mà không gặp lỗi. Sau khi nó được in, chúng tôi chỉ cần đưa ra bỏ [] để đóng chương trình, vì chúng tôi đã có mật khẩu
- đừng bỏ lỡ. Cách bẻ khóa mật khẩu nhanh bằng Hashcat
Nếu biến hashGuess và sha1hash không khớp, chúng tôi sẽ cần giải thích những việc cần làm. Chúng ta có thể thêm phần này của câu lệnh bằng câu lệnh elif. Elif hoặc "else if" cho chương trình biết phải làm gì nếu một điều kiện khác là đúng. Tuyên bố tiếp theo của chúng tôi để kiểm tra trong trường hợp này là như sau
import hashlib, bcrypt
#Demonstrates the difference between two types of hashing, SHA1 and Bcrypt
password = input["Input the password to hash\n>"]
print["\nSHA1:\n"]
for i in range[3]:
setpass = bytes[password, 'utf-8']
hash_object = hashlib.sha1[setpass]
guess_pw = hash_object.hexdigest[]
print[guess_pw]
print["\nMD5:\n"]
for i in range[3]:
setpass = bytes[password, 'utf-8']
hash_object = hashlib.md5[setpass]
guess_pw = hash_object.hexdigest[]
print[guess_pw]
print["\nBCRYPT:\n"]
for i in range[3]:
hashed = bcrypt.hashpw[setpass, bcrypt.gensalt[10]]
8Câu lệnh này hỏi nếu hai biến không bằng nhau, được hiển thị với. = biểu tượng. Nếu điều này là đúng, hay nói cách khác, nếu hai giá trị băm không bằng nhau và đoán sai mật khẩu, chúng tôi sẽ cần thông báo cho người dùng rằng việc đoán không thành công, sau đó quay lại đầu vòng lặp để lấy một
Để làm điều này, chúng ta sẽ làm điều tương tự như chúng ta đã làm trước đây và chỉ cần sử dụng hàm print[] để in ra một tin nhắn. Trong tin nhắn này, chúng tôi sẽ nói. "Đoán mật khẩu", [đoán], "không khớp, thử tiếp theo. ". Kết quả cuối cùng sẽ giống như mã bên dưới
import hashlib, bcrypt
#Demonstrates the difference between two types of hashing, SHA1 and Bcrypt
password = input["Input the password to hash\n>"]
print["\nSHA1:\n"]
for i in range[3]:
setpass = bytes[password, 'utf-8']
hash_object = hashlib.sha1[setpass]
guess_pw = hash_object.hexdigest[]
print[guess_pw]
print["\nMD5:\n"]
for i in range[3]:
setpass = bytes[password, 'utf-8']
hash_object = hashlib.md5[setpass]
guess_pw = hash_object.hexdigest[]
print[guess_pw]
print["\nBCRYPT:\n"]
for i in range[3]:
hashed = bcrypt.hashpw[setpass, bcrypt.gensalt[10]]
9Mã này giải thích những việc cần làm nếu dự đoán là đúng và phải làm gì nếu các dự đoán không khớp, nhưng nếu chúng ta hoàn toàn không tìm thấy kết quả phù hợp thì sao?
Bước 7. Cho chương trình biết phải làm gì nếu không có kết quả phù hợp
Nếu chúng ta đi hết vòng lặp này và không tìm thấy kết quả trùng khớp, vòng lặp sẽ kết thúc vì sẽ không còn gì để lấy từ danh sách đoán mật khẩu. Chúng tôi sẽ cho người dùng biết rằng chúng tôi đã không thành công thay vì thoát khỏi chương trình đột ngột bằng cách đặt một câu lệnh in ngay bên ngoài vòng lặp. Bằng cách này, nếu mật khẩu được tìm thấy, chức năng in cuối cùng sẽ không bao giờ thực thi vì chức năng thoát [] mà chúng tôi đã thêm trước đó để kết thúc chương trình khi chúng tôi nhận được đúng mật khẩu
Vậy làm cách nào để đặt câu lệnh này bên ngoài vòng lặp?
/Users/skickar/venv/untitled10/bin/python /Users/skickar/Desktop/TestSHA1.py
Input the password to hash
>nullbyte
SHA1:
32c0ced56f1fe08583bdb079d85a35a81995018c
32c0ced56f1fe08583bdb079d85a35a81995018c
32c0ced56f1fe08583bdb079d85a35a81995018c
MD5:
5f804b61f8dcf70044ad8c1385e946a8
5f804b61f8dcf70044ad8c1385e946a8
5f804b61f8dcf70044ad8c1385e946a8
BCRYPT:
b'$2b$10$Z1WVDUi50fmqyrpw19rIyOLPIKVUFeh7HO0FfQi1MbKjyxyduG2WS'
b'$2b$10$F.vehMYSUh/6zmTR/VY2quTnPfzPDcIdHTfZpb8twqjRIIIEFcbUW'
b'$2b$10$pZyptPPDHrnIgpU7wTW2nu4cfGAUS65kcGZb6FMC7KmYwJmuwSoLO'
0Python sẽ thực thi vòng lặp for trước, sau đó đánh giá các câu lệnh if và elif, và chỉ khi vòng lặp kết thúc mới thực thi hàm in cuối cùng, bởi vì nó nằm ngoài vòng lặp for
Chức năng in này đơn giản và không chứa biến, chỉ là một chuỗi để cho người dùng biết rằng chúng tôi không tìm thấy mật khẩu phù hợp trong danh sách
/Users/skickar/venv/untitled10/bin/python /Users/skickar/Desktop/TestSHA1.py
Input the password to hash
>nullbyte
SHA1:
32c0ced56f1fe08583bdb079d85a35a81995018c
32c0ced56f1fe08583bdb079d85a35a81995018c
32c0ced56f1fe08583bdb079d85a35a81995018c
MD5:
5f804b61f8dcf70044ad8c1385e946a8
5f804b61f8dcf70044ad8c1385e946a8
5f804b61f8dcf70044ad8c1385e946a8
BCRYPT:
b'$2b$10$Z1WVDUi50fmqyrpw19rIyOLPIKVUFeh7HO0FfQi1MbKjyxyduG2WS'
b'$2b$10$F.vehMYSUh/6zmTR/VY2quTnPfzPDcIdHTfZpb8twqjRIIIEFcbUW'
b'$2b$10$pZyptPPDHrnIgpU7wTW2nu4cfGAUS65kcGZb6FMC7KmYwJmuwSoLO'
1Với dòng cuối cùng này, chúng ta có một chương trình brute-force SHA-1 đầy đủ chức năng, vì vậy hãy chạy nó. Đầu tiên, chúng tôi nhận được lời nhắc yêu cầu bẻ khóa hàm băm SHA-1. Tôi sẽ cung cấp cho nó hàm băm cbfdac6008f9cab4083784cbd1874f76618d2a97 để kiểm tra
/Users/skickar/venv/untitled10/bin/python /Users/skickar/Desktop/TestSHA1.py
Input the password to hash
>nullbyte
SHA1:
32c0ced56f1fe08583bdb079d85a35a81995018c
32c0ced56f1fe08583bdb079d85a35a81995018c
32c0ced56f1fe08583bdb079d85a35a81995018c
MD5:
5f804b61f8dcf70044ad8c1385e946a8
5f804b61f8dcf70044ad8c1385e946a8
5f804b61f8dcf70044ad8c1385e946a8
BCRYPT:
b'$2b$10$Z1WVDUi50fmqyrpw19rIyOLPIKVUFeh7HO0FfQi1MbKjyxyduG2WS'
b'$2b$10$F.vehMYSUh/6zmTR/VY2quTnPfzPDcIdHTfZpb8twqjRIIIEFcbUW'
b'$2b$10$pZyptPPDHrnIgpU7wTW2nu4cfGAUS65kcGZb6FMC7KmYwJmuwSoLO'
2Sau khi nhấn quay lại, tập lệnh bắt đầu hoạt động
/Users/skickar/venv/untitled10/bin/python /Users/skickar/Desktop/TestSHA1.py
Input the password to hash
>nullbyte
SHA1:
32c0ced56f1fe08583bdb079d85a35a81995018c
32c0ced56f1fe08583bdb079d85a35a81995018c
32c0ced56f1fe08583bdb079d85a35a81995018c
MD5:
5f804b61f8dcf70044ad8c1385e946a8
5f804b61f8dcf70044ad8c1385e946a8
5f804b61f8dcf70044ad8c1385e946a8
BCRYPT:
b'$2b$10$Z1WVDUi50fmqyrpw19rIyOLPIKVUFeh7HO0FfQi1MbKjyxyduG2WS'
b'$2b$10$F.vehMYSUh/6zmTR/VY2quTnPfzPDcIdHTfZpb8twqjRIIIEFcbUW'
b'$2b$10$pZyptPPDHrnIgpU7wTW2nu4cfGAUS65kcGZb6FMC7KmYwJmuwSoLO'
3Và cứ như vậy, chúng tôi đã tìm thấy mật khẩu được sử dụng để tạo hàm băm, cho phép chúng tôi đảo ngược hàm băm SHA-1 "một chiều"
Python thú vị và mạnh mẽ, hãy rút ngắn nó
Với một số kiến thức Python3 đơn giản, chúng tôi có thể viết một tập lệnh đơn giản để tìm mật khẩu mà hàm băm được lấy từ chỉ trong 11 dòng. Bạn có thể xem toàn bộ mã mà không cần bình luận bên dưới. Với một số định dạng thông minh của Python, chúng ta có thể làm cho nó nhỏ gọn hơn [nhưng khó đọc hoặc khó hiểu hơn nhiều] và thực hiện tất cả những điều này chỉ với ba dòng mã
/Users/skickar/venv/untitled10/bin/python /Users/skickar/Desktop/TestSHA1.py
Input the password to hash
>nullbyte
SHA1:
32c0ced56f1fe08583bdb079d85a35a81995018c
32c0ced56f1fe08583bdb079d85a35a81995018c
32c0ced56f1fe08583bdb079d85a35a81995018c
MD5:
5f804b61f8dcf70044ad8c1385e946a8
5f804b61f8dcf70044ad8c1385e946a8
5f804b61f8dcf70044ad8c1385e946a8
BCRYPT:
b'$2b$10$Z1WVDUi50fmqyrpw19rIyOLPIKVUFeh7HO0FfQi1MbKjyxyduG2WS'
b'$2b$10$F.vehMYSUh/6zmTR/VY2quTnPfzPDcIdHTfZpb8twqjRIIIEFcbUW'
b'$2b$10$pZyptPPDHrnIgpU7wTW2nu4cfGAUS65kcGZb6FMC7KmYwJmuwSoLO'
4Điều này có thể thực hiện được bằng cách bẻ khóa hàm băm trên cùng một dòng mà chúng tôi sử dụng để nhập thư viện và bằng cách cô đọng các câu lệnh for và if thành một dòng với một thứ được gọi là toán tử bậc ba. Nói chung, định dạng cho những thứ này là như sau và có thể được thêm vào bao lâu tùy ý
/Users/skickar/venv/untitled10/bin/python /Users/skickar/Desktop/TestSHA1.py
Input the password to hash
>nullbyte
SHA1:
32c0ced56f1fe08583bdb079d85a35a81995018c
32c0ced56f1fe08583bdb079d85a35a81995018c
32c0ced56f1fe08583bdb079d85a35a81995018c
MD5:
5f804b61f8dcf70044ad8c1385e946a8
5f804b61f8dcf70044ad8c1385e946a8
5f804b61f8dcf70044ad8c1385e946a8
BCRYPT:
b'$2b$10$Z1WVDUi50fmqyrpw19rIyOLPIKVUFeh7HO0FfQi1MbKjyxyduG2WS'
b'$2b$10$F.vehMYSUh/6zmTR/VY2quTnPfzPDcIdHTfZpb8twqjRIIIEFcbUW'
b'$2b$10$pZyptPPDHrnIgpU7wTW2nu4cfGAUS65kcGZb6FMC7KmYwJmuwSoLO'
5Trong tập lệnh của chúng tôi, định dạng chúng tôi sẽ sử dụng là
/Users/skickar/venv/untitled10/bin/python /Users/skickar/Desktop/TestSHA1.py
Input the password to hash
>nullbyte
SHA1:
32c0ced56f1fe08583bdb079d85a35a81995018c
32c0ced56f1fe08583bdb079d85a35a81995018c
32c0ced56f1fe08583bdb079d85a35a81995018c
MD5:
5f804b61f8dcf70044ad8c1385e946a8
5f804b61f8dcf70044ad8c1385e946a8
5f804b61f8dcf70044ad8c1385e946a8
BCRYPT:
b'$2b$10$Z1WVDUi50fmqyrpw19rIyOLPIKVUFeh7HO0FfQi1MbKjyxyduG2WS'
b'$2b$10$F.vehMYSUh/6zmTR/VY2quTnPfzPDcIdHTfZpb8twqjRIIIEFcbUW'
b'$2b$10$pZyptPPDHrnIgpU7wTW2nu4cfGAUS65kcGZb6FMC7KmYwJmuwSoLO'
6Sau khi áp dụng những thay đổi này, chúng ta có thể cô đọng mã của mình như ví dụ bên dưới
/Users/skickar/venv/untitled10/bin/python /Users/skickar/Desktop/TestSHA1.py
Input the password to hash
>nullbyte
SHA1:
32c0ced56f1fe08583bdb079d85a35a81995018c
32c0ced56f1fe08583bdb079d85a35a81995018c
32c0ced56f1fe08583bdb079d85a35a81995018c
MD5:
5f804b61f8dcf70044ad8c1385e946a8
5f804b61f8dcf70044ad8c1385e946a8
5f804b61f8dcf70044ad8c1385e946a8
BCRYPT:
b'$2b$10$Z1WVDUi50fmqyrpw19rIyOLPIKVUFeh7HO0FfQi1MbKjyxyduG2WS'
b'$2b$10$F.vehMYSUh/6zmTR/VY2quTnPfzPDcIdHTfZpb8twqjRIIIEFcbUW'
b'$2b$10$pZyptPPDHrnIgpU7wTW2nu4cfGAUS65kcGZb6FMC7KmYwJmuwSoLO'
7Mặc dù điều này thật kinh khủng đối với một người mới sử dụng Python để hiểu mà không có bình luận, nhưng Python có thể được cô đọng từ một ý tưởng sơ bộ thành một vài dòng mã ngắn gọn chỉ bằng cách làm việc thông qua chương trình và tìm kiếm các phím tắt
Nếu bạn muốn chuyển dòng này thành một dòng, bạn chỉ cần bọc nó trong hàm exec[] và thêm các ký tự xuống dòng [\n] mới cho mỗi ngắt dòng mới. Tại sao bạn lại làm điều này, tôi không chắc, nhưng sẽ rất hữu ích khi có thể cô đọng các chương trình khi cần
Tôi hy vọng bạn thích hướng dẫn dành cho người mới bắt đầu này để viết SHA-1 brute-forcer của riêng bạn bằng Python. Nếu bạn có bất kỳ câu hỏi nào về hướng dẫn này hoặc lập trình Python cơ bản, vui lòng để lại nhận xét bên dưới hoặc liên hệ với tôi trên Twitter @KodyKinzie
đừng bỏ lỡ. Tất cả các hướng dẫn bẻ khóa mật khẩu của Null Byte
Bạn muốn bắt đầu kiếm tiền với tư cách là một hacker mũ trắng?