Python Digital Network Forensics-II
Chương trước đã đề cập đến một số khái niệm về pháp y mạng bằng Python. Trong chương này, chúng ta hãy hiểu về pháp y mạng bằng Python ở cấp độ sâu hơn.
Bảo quản trang web với món súp đẹp mắt
World Wide Web (WWW) là một nguồn thông tin duy nhất. Tuy nhiên, di sản của nó đang có nguy cơ cao do mất nội dung ở mức báo động. Một số di sản văn hóa và các tổ chức học thuật, các tổ chức phi lợi nhuận và các doanh nghiệp tư nhân đã tìm hiểu các vấn đề liên quan và đóng góp vào việc phát triển các giải pháp kỹ thuật cho lưu trữ web.
Bảo quản trang web hoặc lưu trữ web là quá trình thu thập dữ liệu từ World Wide Web, đảm bảo rằng dữ liệu được bảo quản trong kho lưu trữ và cung cấp cho các nhà nghiên cứu, sử gia và công chúng trong tương lai. Trước khi tiếp tục đi sâu hơn vào bảo quản trang web, chúng ta hãy thảo luận một số vấn đề quan trọng liên quan đến bảo quản trang web như được đưa ra bên dưới -
Change in Web Resources - Tài nguyên web thay đổi hàng ngày là một thách thức đối với việc bảo quản trang web.
Large Quantity of Resources - Một vấn đề khác liên quan đến bảo quản trang web là số lượng lớn tài nguyên cần được bảo quản.
Integrity - Các trang web phải được bảo vệ khỏi các sửa đổi, xóa hoặc gỡ bỏ trái phép để bảo vệ tính toàn vẹn của nó.
Dealing with multimedia data - Trong khi bảo quản các trang web, chúng tôi cũng cần xử lý dữ liệu đa phương tiện và những dữ liệu này có thể gây ra sự cố khi làm như vậy.
Providing access - Bên cạnh việc bảo tồn, vấn đề cung cấp quyền truy cập tài nguyên web và xử lý các vấn đề về quyền sở hữu cũng cần được giải quyết.
Trong chương này, chúng ta sẽ sử dụng thư viện Python có tên Beautiful Soup để bảo quản trang web.
Beautiful Soup là gì?
Beautiful Soup là một thư viện Python để lấy dữ liệu ra khỏi các tệp HTML và XML. Nó có thể được sử dụng vớiurlibbởi vì nó cần một đầu vào (tài liệu hoặc url) để tạo một đối tượng súp, vì nó không thể tự tìm nạp trang web. Bạn có thể tìm hiểu chi tiết về điều này tại www.crummy.com/software/BeautifulSoup/bs4/doc/
Lưu ý rằng trước khi sử dụng nó, chúng ta phải cài đặt thư viện của bên thứ ba bằng lệnh sau:
pip install bs4
Tiếp theo, sử dụng trình quản lý gói Anaconda, chúng ta có thể cài đặt Beautiful Soup như sau:
conda install -c anaconda beautifulsoup4
Tập lệnh Python để bảo quản các trang web
Tập lệnh Python để bảo quản các trang web bằng cách sử dụng thư viện của bên thứ ba có tên là Beautiful Soup được thảo luận ở đây -
Đầu tiên, nhập các thư viện bắt buộc như sau:
from __future__ import print_function
import argparse
from bs4 import BeautifulSoup, SoupStrainer
from datetime import datetime
import hashlib
import logging
import os
import ssl
import sys
from urllib.request import urlopen
import urllib.error
logger = logging.getLogger(__name__)
Lưu ý rằng tập lệnh này sẽ có hai đối số vị trí, một là URL sẽ được giữ nguyên và một là thư mục đầu ra mong muốn như được hiển thị bên dưới -
if __name__ == "__main__":
parser = argparse.ArgumentParser('Web Page preservation')
parser.add_argument("DOMAIN", help="Website Domain")
parser.add_argument("OUTPUT_DIR", help="Preservation Output Directory")
parser.add_argument("-l", help="Log file path",
default=__file__[:-3] + ".log")
args = parser.parse_args()
Bây giờ, hãy thiết lập ghi nhật ký cho tập lệnh bằng cách chỉ định một tệp và trình xử lý luồng đang ở trong vòng lặp và ghi lại quá trình chuyển đổi như được hiển thị:
logger.setLevel(logging.DEBUG)
msg_fmt = logging.Formatter("%(asctime)-15s %(funcName)-10s""%(levelname)-8s %(message)s")
strhndl = logging.StreamHandler(sys.stderr)
strhndl.setFormatter(fmt=msg_fmt)
fhndl = logging.FileHandler(args.l, mode='a')
fhndl.setFormatter(fmt=msg_fmt)
logger.addHandler(strhndl)
logger.addHandler(fhndl)
logger.info("Starting BS Preservation")
logger.debug("Supplied arguments: {}".format(sys.argv[1:]))
logger.debug("System " + sys.platform)
logger.debug("Version " + sys.version)
Bây giờ, chúng ta hãy thực hiện xác nhận đầu vào trên thư mục đầu ra mong muốn như sau:
if not os.path.exists(args.OUTPUT_DIR):
os.makedirs(args.OUTPUT_DIR)
main(args.DOMAIN, args.OUTPUT_DIR)
Bây giờ, chúng ta sẽ xác định main() hàm này sẽ trích xuất tên cơ sở của trang web bằng cách loại bỏ các phần tử không cần thiết trước tên thực cùng với xác thực bổ sung trên URL đầu vào như sau:
def main(website, output_dir):
base_name = website.replace("https://", "").replace("http://", "").replace("www.", "")
link_queue = set()
if "http://" not in website and "https://" not in website:
logger.error("Exiting preservation - invalid user input: {}".format(website))
sys.exit(1)
logger.info("Accessing {} webpage".format(website))
context = ssl._create_unverified_context()
Bây giờ, chúng ta cần mở một kết nối với URL bằng cách sử dụng phương thức urlopen (). Hãy để chúng tôi sử dụng khối try-trừ như sau:
try:
index = urlopen(website, context=context).read().decode("utf-8")
except urllib.error.HTTPError as e:
logger.error("Exiting preservation - unable to access page: {}".format(website))
sys.exit(2)
logger.debug("Successfully accessed {}".format(website))
Các dòng mã tiếp theo bao gồm ba chức năng như được giải thích bên dưới:
write_output() để ghi trang web đầu tiên vào thư mục đầu ra
find_links() chức năng xác định các liên kết trên trang web này
recurse_pages() có chức năng lặp lại và khám phá tất cả các liên kết trên trang web.
write_output(website, index, output_dir)
link_queue = find_links(base_name, index, link_queue)
logger.info("Found {} initial links on webpage".format(len(link_queue)))
recurse_pages(website, link_queue, context, output_dir)
logger.info("Completed preservation of {}".format(website))
Bây giờ, chúng ta hãy xác định write_output() phương pháp như sau -
def write_output(name, data, output_dir, counter=0):
name = name.replace("http://", "").replace("https://", "").rstrip("//")
directory = os.path.join(output_dir, os.path.dirname(name))
if not os.path.exists(directory) and os.path.dirname(name) != "":
os.makedirs(directory)
Chúng tôi cần ghi lại một số chi tiết về trang web và sau đó chúng tôi ghi lại hàm băm của dữ liệu bằng cách sử dụng hash_data() phương pháp như sau -
logger.debug("Writing {} to {}".format(name, output_dir)) logger.debug("Data Hash: {}".format(hash_data(data)))
path = os.path.join(output_dir, name)
path = path + "_" + str(counter)
with open(path, "w") as outfile:
outfile.write(data)
logger.debug("Output File Hash: {}".format(hash_file(path)))
Bây giờ, xác định hash_data() với sự trợ giúp của chúng tôi đọc UTF-8 dữ liệu được mã hóa và sau đó tạo SHA-256 băm của nó như sau:
def hash_data(data):
sha256 = hashlib.sha256()
sha256.update(data.encode("utf-8"))
return sha256.hexdigest()
def hash_file(file):
sha256 = hashlib.sha256()
with open(file, "rb") as in_file:
sha256.update(in_file.read())
return sha256.hexdigest()
Bây giờ, chúng ta hãy tạo một Beautifulsoup đối tượng ra khỏi dữ liệu trang web dưới find_links() phương pháp như sau -
def find_links(website, page, queue):
for link in BeautifulSoup(page, "html.parser",parse_only = SoupStrainer("a", href = True)):
if website in link.get("href"):
if not os.path.basename(link.get("href")).startswith("#"):
queue.add(link.get("href"))
return queue
Bây giờ, chúng ta cần xác định recurse_pages() bằng cách cung cấp cho nó các đầu vào của URL trang web, hàng đợi liên kết hiện tại, ngữ cảnh SSL chưa được xác minh và thư mục đầu ra như sau:
def recurse_pages(website, queue, context, output_dir):
processed = []
counter = 0
while True:
counter += 1
if len(processed) == len(queue):
break
for link in queue.copy(): if link in processed:
continue
processed.append(link)
try:
page = urlopen(link, context=context).read().decode("utf-8")
except urllib.error.HTTPError as e:
msg = "Error accessing webpage: {}".format(link)
logger.error(msg)
continue
Bây giờ, ghi đầu ra của mỗi trang web được truy cập vào một tệp bằng cách chuyển tên liên kết, dữ liệu trang, thư mục đầu ra và bộ đếm như sau:
write_output(link, page, output_dir, counter)
queue = find_links(website, page, queue)
logger.info("Identified {} links throughout website".format(
len(queue)))
Bây giờ, khi chúng tôi chạy tập lệnh này bằng cách cung cấp URL của trang web, thư mục đầu ra và đường dẫn đến tệp nhật ký, chúng tôi sẽ nhận được thông tin chi tiết về trang web đó có thể được sử dụng để sử dụng trong tương lai.
Săn virus
Bạn đã bao giờ tự hỏi làm thế nào các nhà phân tích pháp y, nhà nghiên cứu bảo mật và người trả lời sự cố có thể hiểu được sự khác biệt giữa phần mềm hữu ích và phần mềm độc hại? Câu trả lời nằm trong chính câu hỏi, bởi vì nếu không nghiên cứu về phần mềm độc hại, do tin tặc tạo ra nhanh chóng, các nhà nghiên cứu và chuyên gia sẽ không thể phân biệt được sự khác biệt giữa phần mềm hữu ích và phần mềm độc hại. Trong phần này, chúng ta hãy thảo luận vềVirusShare, một công cụ để hoàn thành nhiệm vụ này.
Hiểu biết về VirusShare
VirusShare là bộ sưu tập mẫu phần mềm độc hại thuộc sở hữu tư nhân lớn nhất để cung cấp cho các nhà nghiên cứu bảo mật, người ứng phó sự cố và nhà phân tích pháp y các mẫu mã độc trực tiếp. Nó chứa hơn 30 triệu mẫu.
Lợi ích của VirusShare là danh sách các mã băm phần mềm độc hại có sẵn miễn phí. Bất kỳ ai cũng có thể sử dụng các hàm băm này để tạo một bộ băm rất toàn diện và sử dụng bộ băm đó để xác định các tệp có khả năng độc hại. Nhưng trước khi sử dụng VirusShare, chúng tôi khuyên bạn nên truy cậphttps://virusshare.com để biết thêm chi tiết.
Tạo danh sách băm được phân cách dòng mới từ VirusShare bằng Python
Danh sách băm từ VirusShare có thể được sử dụng bởi các công cụ pháp y khác nhau như X-way và EnCase. Trong tập lệnh được thảo luận bên dưới, chúng tôi sẽ tự động tải xuống danh sách băm từ VirusShare để tạo danh sách băm được phân tách bằng dòng mới.
Đối với tập lệnh này, chúng tôi cần một thư viện Python của bên thứ ba tqdm có thể tải xuống như sau:
pip install tqdm
Lưu ý rằng trong tập lệnh này, trước tiên chúng ta sẽ đọc trang băm VirusShare và xác định động danh sách băm gần đây nhất. Sau đó, chúng tôi sẽ khởi tạo thanh tiến trình và tải xuống danh sách băm trong phạm vi mong muốn.
Đầu tiên, nhập các thư viện sau:
from __future__ import print_function
import argparse
import os
import ssl
import sys
import tqdm
from urllib.request import urlopen
import urllib.error
Tập lệnh này sẽ nhận một đối số vị trí, đó sẽ là đường dẫn mong muốn cho tập băm -
if __name__ == '__main__':
parser = argparse.ArgumentParser('Hash set from VirusShare')
parser.add_argument("OUTPUT_HASH", help = "Output Hashset")
parser.add_argument("--start", type = int, help = "Optional starting location")
args = parser.parse_args()
Bây giờ, chúng tôi sẽ thực hiện xác nhận đầu vào tiêu chuẩn như sau:
directory = os.path.dirname(args.OUTPUT_HASH)
if not os.path.exists(directory):
os.makedirs(directory)
if args.start:
main(args.OUTPUT_HASH, start=args.start)
else:
main(args.OUTPUT_HASH)
Bây giờ chúng ta cần xác định main() chức năng với **kwargs như một đối số vì điều này sẽ tạo ra một từ điển mà chúng ta có thể tham khảo để hỗ trợ các đối số chính được cung cấp như được hiển thị bên dưới:
def main(hashset, **kwargs):
url = "https://virusshare.com/hashes.4n6"
print("[+] Identifying hash set range from {}".format(url))
context = ssl._create_unverified_context()
Bây giờ, chúng ta cần mở trang băm VirusShare bằng cách sử dụng urlib.request.urlopen()phương pháp. Chúng tôi sẽ sử dụng khối thử ngoại trừ như sau:
try:
index = urlopen(url, context = context).read().decode("utf-8")
except urllib.error.HTTPError as e:
print("[-] Error accessing webpage - exiting..")
sys.exit(1)
Bây giờ, xác định danh sách băm mới nhất từ các trang đã tải xuống. Bạn có thể làm điều này bằng cách tìm phiên bản cuối cùng của HTMLhrefvào danh sách băm VirusShare. Nó có thể được thực hiện với các dòng mã sau:
tag = index.rfind(r'a href = "hashes/VirusShare_')
stop = int(index[tag + 27: tag + 27 + 5].lstrip("0"))
if "start" not in kwa<rgs:
start = 0
else:
start = kwargs["start"]
if start < 0 or start > stop:
print("[-] Supplied start argument must be greater than or equal ""to zero but less than the latest hash list, ""currently: {}".format(stop))
sys.exit(2)
print("[+] Creating a hashset from hash lists {} to {}".format(start, stop))
hashes_downloaded = 0
Bây giờ, chúng ta sẽ sử dụng tqdm.trange() phương pháp tạo vòng lặp và thanh tiến trình như sau:
for x in tqdm.trange(start, stop + 1, unit_scale=True,desc="Progress"):
url_hash = "https://virusshare.com/hashes/VirusShare_"\"{}.md5".format(str(x).zfill(5))
try:
hashes = urlopen(url_hash, context=context).read().decode("utf-8")
hashes_list = hashes.split("\n")
except urllib.error.HTTPError as e:
print("[-] Error accessing webpage for hash list {}"" - continuing..".format(x))
continue
Sau khi thực hiện các bước trên thành công, chúng ta sẽ mở tệp văn bản bộ băm ở chế độ + để nối vào cuối tệp văn bản.
with open(hashset, "a+") as hashfile:
for line in hashes_list:
if not line.startswith("#") and line != "":
hashes_downloaded += 1
hashfile.write(line + '\n')
print("[+] Finished downloading {} hashes into {}".format(
hashes_downloaded, hashset))
Sau khi chạy tập lệnh trên, bạn sẽ nhận được danh sách băm mới nhất chứa các giá trị băm MD5 ở định dạng văn bản.