Vũ phu trong python là gì?

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]]
1

Mã 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]]
2

Bâ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]]
3

Vì 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]]
4

Bâ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]]
6

Bâ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]]
8

Câ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]]
9

Mã 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'
0

Python 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'
1

Vớ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'
2

Sau 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'
3

Và 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'
5

Trong 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'
6

Sau 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'
7

Mặ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?

Brute force trong lập trình là gì?

lực lượng vũ phu. tính từ. Mô tả phong cách lập trình nguyên thủy, trong đó lập trình viên dựa vào sức mạnh xử lý của máy tính thay vì sử dụng trí thông minh của mình để đơn giản hóa vấn đề, thường bỏ qua các vấn đề về quy mô và áp dụng các phương pháp ngây thơ phù hợp trực tiếp với các vấn đề nhỏ cho các vấn đề lớn

Lực lượng vũ phu trong AI là gì?

Cách tiếp cận mạnh mẽ là một cách để giải quyết vấn đề bằng cách thử tất cả các giải pháp có thể . Thuật toán brute force thử mọi cách cho đến khi không thể tìm ra giải pháp hiệu quả.

Lực lượng vũ phu trong học máy là gì?

Tấn công vũ phu là một cách thông thường để bẻ khóa mật khẩu dựa trên từ điển thủ công. Theo truyền thống, từ điển này được xây dựng bằng cách sử dụng nhóm hiện có, từ ngẫu nhiên, từ có nghĩa từ trang web công cộng hoặc mật khẩu trước đó, khiến cho cuộc tấn công vũ phu mất nhiều thời gian và tiêu tốn nhiều tài nguyên

Chủ Đề