Pháp y kỹ thuật số Python - Hướng dẫn nhanh
Chương này sẽ cung cấp cho bạn phần giới thiệu về pháp y kỹ thuật số là gì và đánh giá lịch sử của nó. Bạn cũng sẽ hiểu nơi bạn có thể áp dụng pháp y kỹ thuật số trong cuộc sống thực và những hạn chế của nó.
Pháp y kỹ thuật số là gì?
Pháp y kỹ thuật số có thể được định nghĩa là ngành của khoa học pháp y phân tích, kiểm tra, xác định và thu hồi các bằng chứng kỹ thuật số trên các thiết bị điện tử. Nó thường được sử dụng cho luật hình sự và điều tra tư nhân.
Ví dụ: bạn có thể dựa vào pháp y kỹ thuật số trích xuất bằng chứng trong trường hợp ai đó đánh cắp một số dữ liệu trên thiết bị điện tử.
Đánh giá lịch sử ngắn gọn về pháp y kỹ thuật số
Lịch sử của tội phạm máy tính và quá trình đánh giá lịch sử của pháp y kỹ thuật số được giải thích trong phần này như dưới đây:
1970-1980: Tội phạm máy tính đầu tiên
Trước thập kỷ này, không có tội phạm máy tính nào được công nhận. Tuy nhiên, nếu điều đó được cho là xảy ra, thì các luật hiện hành đã xử lý chúng. Sau đó, vào năm 1978, tội phạm máy tính đầu tiên được công nhận trong Đạo luật Tội phạm Máy tính Florida, bao gồm luật chống lại việc sửa đổi hoặc xóa trái phép dữ liệu trên hệ thống máy tính. Nhưng theo thời gian, do sự tiến bộ của công nghệ, phạm vi tội phạm máy tính được thực hiện cũng tăng lên. Để đối phó với các tội phạm liên quan đến bản quyền, quyền riêng tư và nội dung khiêu dâm trẻ em, nhiều luật khác đã được thông qua.
1980-1990: Thập kỷ phát triển
Thập kỷ này là thập kỷ phát triển của pháp y kỹ thuật số, tất cả là vì cuộc điều tra đầu tiên (1986), trong đó Cliff Stoll theo dõi tin tặc có tên Markus Hess. Trong thời kỳ này, hai loại pháp y kỹ thuật số được phát triển - đầu tiên là với sự trợ giúp của các công cụ và kỹ thuật đặc biệt được phát triển bởi những người thực hành coi nó như một sở thích, trong khi thứ hai được phát triển bởi cộng đồng khoa học. Năm 1992, thuật ngữ“Computer Forensics”đã được sử dụng trong văn học hàn lâm.
Những năm 2000-2010: Thập kỷ tiêu chuẩn hóa
Sau sự phát triển của pháp y kỹ thuật số đến một mức độ nhất định, cần phải đưa ra một số tiêu chuẩn cụ thể có thể được tuân theo trong khi thực hiện điều tra. Theo đó, các cơ quan và cơ quan khoa học khác nhau đã xuất bản các hướng dẫn về pháp y kỹ thuật số. Năm 2002, Nhóm Công tác Khoa học về Bằng chứng Kỹ thuật số (SWGDE) đã xuất bản một bài báo có tên “Các phương pháp hay nhất cho Pháp y Máy tính”. Một chiếc lông khác trên mũ là một hiệp ước quốc tế do Châu Âu đứng đầu, cụ thể là“The Convention on Cybercrime”đã được 43 quốc gia ký kết và 16 quốc gia phê chuẩn. Ngay cả sau những tiêu chuẩn như vậy, vẫn cần phải giải quyết một số vấn đề đã được các nhà nghiên cứu xác định.
Quy trình pháp y kỹ thuật số
Kể từ lần đầu tiên tội phạm máy tính xảy ra vào năm 1978, có một sự gia tăng lớn trong các hoạt động tội phạm kỹ thuật số. Do sự gia tăng này, cần có cách thức có cấu trúc để đối phó với chúng. Năm 1984, một quy trình chính thức hóa đã được đưa ra và sau đó, một số lượng lớn các quy trình điều tra pháp y máy tính mới và cải tiến đã được phát triển.
Quá trình điều tra pháp y máy tính bao gồm ba giai đoạn chính như được giải thích bên dưới:
Giai đoạn 1: Mua lại hoặc Hình ảnh các Vật trưng bày
Giai đoạn đầu tiên của pháp y kỹ thuật số liên quan đến việc lưu trạng thái của hệ thống kỹ thuật số để có thể phân tích sau này. Nó rất giống với việc chụp ảnh, mẫu máu, v.v. từ hiện trường vụ án. Ví dụ, nó liên quan đến việc chụp ảnh các vùng được phân bổ và không được phân bổ của đĩa cứng hoặc RAM.
Giai đoạn 2: Phân tích
Đầu vào của giai đoạn này là dữ liệu thu được trong giai đoạn thu nhận. Tại đây, dữ liệu này đã được kiểm tra để xác định bằng chứng. Giai đoạn này đưa ra ba loại bằng chứng như sau:
Inculpatory evidences - Những bằng chứng này hỗ trợ một lịch sử nhất định.
Exculpatory evidences - Những bằng chứng này mâu thuẫn với một lịch sử nhất định.
Evidence of tampering- Những bằng chứng này cho thấy hệ thống đã được làm nóng để tránh bị nhận dạng. Nó bao gồm việc kiểm tra các tệp và nội dung thư mục để khôi phục các tệp đã bị xóa.
Giai đoạn 3: Trình bày hoặc Báo cáo
Như tên cho thấy, giai đoạn này trình bày kết luận và các bằng chứng tương ứng từ cuộc điều tra.
Các ứng dụng của pháp y kỹ thuật số
Pháp y kỹ thuật số đề cập đến việc thu thập, phân tích và bảo quản các bằng chứng có trong bất kỳ thiết bị kỹ thuật số nào. Việc sử dụng pháp y kỹ thuật số phụ thuộc vào ứng dụng. Như đã đề cập trước đó, nó được sử dụng chủ yếu trong hai ứng dụng sau:
Pháp luật hình sự
Trong luật hình sự, bằng chứng được thu thập để ủng hộ hoặc phản đối một giả thuyết trước tòa. Các thủ tục pháp y rất giống với các thủ tục được sử dụng trong điều tra tội phạm nhưng với các yêu cầu và giới hạn pháp lý khác nhau.
Điều tra cá nhân
Chủ yếu thế giới doanh nghiệp sử dụng pháp y kỹ thuật số để điều tra tư nhân. Nó được sử dụng khi các công ty nghi ngờ rằng nhân viên có thể đang thực hiện một hoạt động bất hợp pháp trên máy tính của họ, trái với chính sách của công ty. Pháp y kỹ thuật số cung cấp một trong những con đường tốt nhất để công ty hoặc cá nhân thực hiện khi điều tra ai đó về hành vi sai trái kỹ thuật số.
Các chi nhánh của pháp y kỹ thuật số
Tội phạm kỹ thuật số không chỉ giới hạn ở máy tính, tuy nhiên tin tặc và tội phạm đang sử dụng các thiết bị kỹ thuật số nhỏ như máy tính bảng, điện thoại thông minh, v.v. ở quy mô rất lớn. Một số thiết bị có bộ nhớ dễ bay hơi, trong khi những thiết bị khác có bộ nhớ không thay đổi. Do đó, tùy thuộc vào loại thiết bị, pháp y kỹ thuật số có các nhánh sau:
Pháp y máy tính
Nhánh pháp y kỹ thuật số này liên quan đến máy tính, hệ thống nhúng và bộ nhớ tĩnh như ổ USB. Nhiều thông tin từ nhật ký đến tệp thực trên ổ đĩa có thể được điều tra trong pháp y máy tính.
Pháp y di động
Điều này liên quan đến việc điều tra dữ liệu từ thiết bị di động. Nhánh này khác với pháp y máy tính ở chỗ các thiết bị di động có một hệ thống liên lạc sẵn có rất hữu ích để cung cấp thông tin hữu ích liên quan đến vị trí.
Pháp y mạng
Điều này liên quan đến việc giám sát và phân tích lưu lượng mạng máy tính, cả nội bộ và WAN (mạng diện rộng) cho các mục đích thu thập thông tin, thu thập bằng chứng hoặc phát hiện xâm nhập.
Cơ sở dữ liệu pháp y
Nhánh pháp y kỹ thuật số này liên quan đến nghiên cứu pháp y về cơ sở dữ liệu và siêu dữ liệu của chúng.
Kỹ năng cần thiết để điều tra pháp y kỹ thuật số
Giám định pháp y kỹ thuật số giúp theo dõi tin tặc, khôi phục dữ liệu bị đánh cắp, theo dõi các cuộc tấn công máy tính trở lại nguồn của chúng và hỗ trợ trong các loại điều tra khác liên quan đến máy tính. Một số kỹ năng chính cần thiết để trở thành giám định viên pháp y kỹ thuật số như được thảo luận bên dưới -
Khả năng tư duy vượt trội
Một điều tra viên pháp y kỹ thuật số phải là một nhà tư tưởng xuất sắc và phải có khả năng áp dụng các công cụ và phương pháp luận khác nhau vào một nhiệm vụ cụ thể để thu được kết quả đầu ra. Anh ấy / cô ấy phải có khả năng tìm ra các mẫu khác nhau và tạo mối tương quan giữa chúng.
Kĩ năng công nghệ
Một giám định viên pháp y kỹ thuật số phải có kỹ năng công nghệ tốt vì lĩnh vực này đòi hỏi kiến thức về mạng, cách hệ thống kỹ thuật số tương tác.
Đam mê An ninh mạng
Bởi vì lĩnh vực pháp y kỹ thuật số là tất cả về giải quyết tội phạm mạng và đây là một nhiệm vụ tẻ nhạt, nó cần rất nhiều niềm đam mê để một người trở thành điều tra viên pháp y kỹ thuật số giỏi.
Kĩ năng giao tiếp
Kỹ năng giao tiếp tốt là điều bắt buộc để phối hợp với các nhóm khác nhau và trích xuất bất kỳ dữ liệu hoặc thông tin còn thiếu nào.
Có kỹ năng lập báo cáo
Sau khi thực hiện thành công việc thu thập và phân tích, một giám định viên pháp y kỹ thuật số phải đề cập đến tất cả các phát hiện trong báo cáo và bản trình bày cuối cùng. Do đó, người đó phải có kỹ năng lập báo cáo tốt và chú ý đến từng chi tiết.
Hạn chế
Điều tra pháp y kỹ thuật số cung cấp những hạn chế nhất định như đã thảo luận ở đây -
Cần đưa ra bằng chứng thuyết phục
Một trong những trở ngại lớn của điều tra pháp y kỹ thuật số là người giám định phải tuân thủ các tiêu chuẩn được yêu cầu đối với bằng chứng trước tòa vì dữ liệu có thể dễ dàng bị giả mạo. Mặt khác, điều tra viên pháp y máy tính phải có kiến thức đầy đủ về các yêu cầu pháp lý, các thủ tục xử lý chứng cứ và tài liệu để đưa ra chứng cứ thuyết phục trước tòa.
Công cụ điều tra
Hiệu quả của điều tra kỹ thuật số hoàn toàn nằm ở chuyên môn của giám định viên pháp y kỹ thuật số và việc lựa chọn công cụ điều tra thích hợp. Nếu công cụ được sử dụng không theo tiêu chuẩn quy định thì tại tòa án pháp luật, các bằng chứng có thể bị thẩm phán bác bỏ.
Thiếu kiến thức kỹ thuật trong số khán giả
Một hạn chế khác là một số cá nhân chưa hoàn toàn quen thuộc với pháp y máy tính; do đó, nhiều người chưa hiểu rõ về lĩnh vực này. Các nhà điều tra phải đảm bảo thông báo kết quả của họ với tòa án theo cách để giúp mọi người hiểu kết quả.
Giá cả
Sản xuất bằng chứng kỹ thuật số và bảo quản chúng rất tốn kém. Do đó, quá trình này có thể không được nhiều người lựa chọn, những người không có khả năng chi trả.
Trong chương trước, chúng ta đã tìm hiểu những kiến thức cơ bản về pháp y kỹ thuật số, những ưu điểm và hạn chế của nó. Chương này sẽ giúp bạn thoải mái với Python, công cụ thiết yếu mà chúng tôi đang sử dụng trong cuộc điều tra pháp y kỹ thuật số này.
Tại sao sử dụng Python cho pháp y kỹ thuật số?
Python là một ngôn ngữ lập trình phổ biến và được sử dụng làm công cụ bảo mật mạng, kiểm tra thâm nhập cũng như điều tra pháp y kỹ thuật số. Khi bạn chọn Python làm công cụ của mình cho pháp y kỹ thuật số, bạn không cần bất kỳ phần mềm bên thứ ba nào khác để hoàn thành nhiệm vụ.
Dưới đây là một số tính năng độc đáo của ngôn ngữ lập trình Python giúp nó phù hợp với các dự án pháp y kỹ thuật số:
Simplicity of Syntax - Cú pháp của Python rất đơn giản so với các ngôn ngữ khác, giúp người ta dễ dàng học và sử dụng cho pháp y kỹ thuật số hơn.
Comprehensive inbuilt modules - Các mô-đun tích hợp toàn diện của Python là một trợ giúp tuyệt vời để thực hiện một cuộc điều tra pháp y kỹ thuật số hoàn chỉnh.
Help and Support - Là một ngôn ngữ lập trình mã nguồn mở, Python nhận được sự hỗ trợ tuyệt vời từ cộng đồng nhà phát triển và người dùng.
Các tính năng của Python
Python, là một ngôn ngữ kịch bản cấp cao, được thông dịch, tương tác và hướng đối tượng, cung cấp các tính năng sau:
Easy to Learn - Python là một ngôn ngữ thân thiện với nhà phát triển và dễ học, vì nó có ít từ khóa hơn và cấu trúc đơn giản nhất.
Expressive and Easy to read- Ngôn ngữ Python có bản chất biểu cảm; do đó mã của nó dễ hiểu và dễ đọc hơn.
Cross-platform Compatible - Python là một ngôn ngữ tương thích đa nền tảng, có nghĩa là nó có thể chạy hiệu quả trên nhiều nền tảng khác nhau như UNIX, Windows và Macintosh.
Interactive Mode Programming - Chúng tôi có thể thực hiện kiểm tra tương tác và gỡ lỗi mã vì Python hỗ trợ chế độ tương tác để lập trình.
Provides Various Modules and Functions - Python có thư viện tiêu chuẩn lớn cho phép chúng tôi sử dụng tập hợp các mô-đun và chức năng phong phú cho tập lệnh của mình.
Supports Dynamic Type Checking - Python hỗ trợ kiểm tra kiểu động và cung cấp các kiểu dữ liệu động cấp rất cao.
GUI Programming - Python hỗ trợ lập trình GUI để phát triển giao diện người dùng Đồ họa.
Integration with other programming languages - Python có thể dễ dàng tích hợp với các ngôn ngữ lập trình khác như C, C ++, JAVA, v.v.
Cài đặt Python
Bản phân phối Python có sẵn cho nhiều nền tảng khác nhau như Windows, UNIX, Linux và Mac. Chúng tôi chỉ cần tải xuống mã nhị phân theo nền tảng của chúng tôi. Trong trường hợp nếu mã nhị phân cho bất kỳ nền tảng nào không có sẵn, chúng ta phải có trình biên dịch C để mã nguồn có thể được biên dịch theo cách thủ công.
Phần này sẽ giúp bạn làm quen với việc cài đặt Python trên các nền tảng khác nhau−
Cài đặt Python trên Unix và Linux
Bạn có thể làm theo các bước dưới đây để cài đặt Python trên máy Unix / Linux.
Step 1- Mở trình duyệt Web. Nhập và nhập www.python.org/downloads/
Step 2 - Tải xuống mã nguồn nén có sẵn cho Unix / Linux.
Step 3 - Giải nén các tập tin nén đã tải xuống.
Step 4 - Nếu bạn muốn tùy chỉnh một số tùy chọn, bạn có thể chỉnh sửa Modules/Setup file.
Step 5 - Sử dụng các lệnh sau để hoàn tất cài đặt -
run ./configure script
make
make install
Khi bạn đã hoàn thành thành công các bước được đưa ra ở trên, Python sẽ được cài đặt tại vị trí chuẩn của nó /usr/local/bin và các thư viện của nó tại /usr/local/lib/pythonXX trong đó XX là phiên bản của Python.
Cài đặt Python trên Windows
Chúng ta có thể làm theo các bước đơn giản sau để cài đặt Python trên máy Windows.
Step 1- Mở trình duyệt web. Nhập và nhập www.python.org/downloads/
Step 2 - Tải xuống trình cài đặt Windows python-XYZ.msi , trong đó XYZ là phiên bản chúng ta cần cài đặt.
Step 3 - Bây giờ chạy tệp MSI đó sau khi lưu tệp trình cài đặt vào máy cục bộ của bạn.
Step 4 - Chạy tệp đã tải xuống sẽ hiển thị trình hướng dẫn cài đặt Python.
Cài đặt Python trên Macintosh
Để cài đặt Python 3 trên Mac OS X, chúng ta phải sử dụng trình cài đặt gói có tên Homebrew.
Bạn có thể sử dụng lệnh sau để cài đặt Homebrew, trong trường hợp bạn không có nó trên hệ thống của mình -
$ ruby -e "$(curl -fsSL
https://raw.githubusercontent.com/Homebrew/install/master/install)"
Nếu bạn cần cập nhật trình quản lý gói, thì nó có thể được thực hiện với sự trợ giúp của lệnh sau:
$ brew update
Bây giờ, sử dụng lệnh sau để cài đặt Python3 trên hệ thống của bạn:
$ brew install python3
Đặt PATH
Chúng tôi cần thiết lập đường dẫn để cài đặt Python và điều này khác với các nền tảng như UNIX, WINDOWS hoặc MAC.
Cài đặt đường dẫn tại Unix / Linux
Bạn có thể sử dụng các tùy chọn sau để đặt đường dẫn trên Unix / Linux -
If using csh shell - Kiểu setenv PATH "$PATH:/usr/local/bin/python" và sau đó nhấn Enter.
If using bash shell (Linux) - Loại export ATH="$PATH:/usr/local/bin/python" và sau đó nhấn Enter.
If using sh or ksh shell - Kiểu PATH="$PATH:/usr/local/bin/python" và sau đó nhấn Enter.
Thiết lập đường dẫn trên Windows
Kiểu path %path%;C:\Python tại dấu nhắc lệnh và sau đó nhấn Enter.
Chạy Python
Bạn có thể chọn bất kỳ phương pháp nào trong ba phương pháp sau để khởi động trình thông dịch Python:
Phương pháp 1: Sử dụng Trình thông dịch tương tác
Một hệ thống cung cấp trình thông dịch dòng lệnh hoặc trình bao có thể dễ dàng được sử dụng để khởi động Python. Ví dụ: Unix, DOS, v.v. Bạn có thể làm theo các bước dưới đây để bắt đầu viết mã trong trình thông dịch tương tác -
Step 1 - Nhập python tại dòng lệnh.
Step 2 - Bắt đầu viết mã ngay lập tức trong trình thông dịch tương tác bằng các lệnh hiển thị bên dưới -
$python # Unix/Linux
or
python% # Unix/Linux
or
C:> python # Windows/DOS
Phương pháp 2: Sử dụng Script từ dòng lệnh
Chúng tôi cũng có thể thực thi một tập lệnh Python tại dòng lệnh bằng cách gọi trình thông dịch trên ứng dụng của chúng tôi. Bạn có thể sử dụng các lệnh hiển thị bên dưới:
$python script.py # Unix/Linux
or
python% script.py # Unix/Linux
or
C: >python script.py # Windows/DOS
Phương pháp 3: Môi trường phát triển tích hợp
Nếu một hệ thống có ứng dụng GUI hỗ trợ Python, thì Python có thể được chạy từ môi trường GUI đó. Dưới đây là một số IDE cho các nền tảng khác nhau:
Unix IDE - UNIX có IDLE IDE cho Python.
Windows IDE - Windows có PythonWin, giao diện Windows đầu tiên cho Python cùng với GUI.
Macintosh IDE - Macintosh có IDLE IDE có sẵn trên trang web chính, có thể tải xuống dưới dạng tệp MacBinary hoặc BinHex'd.
Bây giờ bạn đã cảm thấy thoải mái với việc cài đặt và chạy các lệnh Python trên hệ thống cục bộ của mình, hãy cùng chúng tôi chuyển sang các khái niệm về pháp y một cách chi tiết. Chương này sẽ giải thích các khái niệm khác nhau liên quan đến việc xử lý các hiện vật trong pháp y kỹ thuật số Python.
Cần tạo báo cáo
Quá trình pháp y kỹ thuật số bao gồm báo cáo như giai đoạn thứ ba. Đây là một trong những phần quan trọng nhất của quy trình pháp y kỹ thuật số. Việc tạo báo cáo là cần thiết vì những lý do sau:
Đây là tài liệu trong đó giám định viên pháp y kỹ thuật số phác thảo quá trình điều tra và những phát hiện của nó.
Một báo cáo pháp y kỹ thuật số tốt có thể được người giám định khác tham khảo để đạt được kết quả tương tự bởi các kho lưu trữ giống nhau.
Nó là một tài liệu khoa học và kỹ thuật chứa các dữ kiện được tìm thấy trong phạm vi 1 và 0 của bằng chứng kỹ thuật số.
Nguyên tắc chung để tạo báo cáo
Các báo cáo được viết để cung cấp thông tin cho người đọc và phải bắt đầu với một nền tảng vững chắc. điều tra viên có thể gặp khó khăn trong việc trình bày hiệu quả các phát hiện của họ nếu báo cáo được chuẩn bị mà không có một số hướng dẫn hoặc tiêu chuẩn chung. Dưới đây là một số nguyên tắc chung phải tuân theo khi tạo báo cáo pháp y kỹ thuật số:
Summary - Báo cáo phải có nội dung tóm tắt thông tin để người đọc có thể xác định được mục đích của báo cáo.
Tools used - Chúng ta phải đề cập đến các công cụ đã được sử dụng để thực hiện quá trình pháp y kỹ thuật số, bao gồm cả mục đích của chúng.
Repository - Giả sử, chúng tôi điều tra máy tính của ai đó, sau đó tóm tắt bằng chứng và phân tích tài liệu liên quan như email, lịch sử tìm kiếm nội bộ, v.v. thì chúng phải được đưa vào báo cáo để vụ việc có thể được trình bày rõ ràng.
Recommendations for counsel - Báo cáo phải có các khuyến nghị cho luật sư để tiếp tục hoặc ngừng điều tra dựa trên các phát hiện trong báo cáo.
Tạo các loại báo cáo khác nhau
Trong phần trên, chúng ta đã biết về tầm quan trọng của báo cáo trong pháp y kỹ thuật số cùng với các nguyên tắc tạo báo cáo tương tự. Một số định dạng trong Python để tạo các loại báo cáo khác nhau được thảo luận bên dưới:
Báo cáo CSV
Một trong những định dạng đầu ra phổ biến nhất của báo cáo là báo cáo bảng tính CSV. Bạn có thể tạo CSV để tạo báo cáo dữ liệu đã xử lý bằng mã Python như hình dưới đây:
Đầu tiên, nhập các thư viện hữu ích để viết bảng tính -
from __future__ import print_function
import csv
import os
import sys
Bây giờ, hãy gọi phương thức sau:
Write_csv(TEST_DATA_LIST, ["Name", "Age", "City", "Job description"], os.getcwd())
Chúng tôi đang sử dụng biến toàn cục sau để đại diện cho các kiểu dữ liệu mẫu:
TEST_DATA_LIST = [["Ram", 32, Bhopal, Manager],
["Raman", 42, Indore, Engg.],
["Mohan", 25, Chandigarh, HR],
["Parkash", 45, Delhi, IT]]
Tiếp theo, chúng ta hãy xác định phương thức để tiến hành các thao tác tiếp theo. Chúng tôi mở tệp ở chế độ “w” và đặt đối số từ khóa dòng mới thành một chuỗi trống.
def Write_csv(data, header, output_directory, name = None):
if name is None:
name = "report1.csv"
print("[+] Writing {} to {}".format(name, output_directory))
with open(os.path.join(output_directory, name), "w", newline = "") as \ csvfile:
writer = csv.writer(csvfile)
writer.writerow(header)
writer.writerow(data)
Nếu bạn chạy tập lệnh trên, bạn sẽ nhận được các chi tiết sau được lưu trữ trong tệp report1.csv.
Tên | Tuổi tác | Tp. | Chỉ định |
---|---|---|---|
Ram | 32 | Bhopal | Quản lý |
Raman | 42 | Indore | Engg |
Mohan | 25 | Chandigarh | Nhân sự |
Parkash | 45 | Delhi | IT |
Báo cáo Excel
Một định dạng đầu ra phổ biến khác của báo cáo là báo cáo bảng tính Excel (.xlsx). Chúng ta có thể tạo bảng và vẽ biểu đồ bằng cách sử dụng Excel. Chúng tôi có thể tạo báo cáo dữ liệu đã xử lý ở định dạng Excel bằng mã Python như hình dưới đây−
Đầu tiên, nhập mô-đun XlsxWriter để tạo bảng tính -
import xlsxwriter
Bây giờ, tạo một đối tượng sổ làm việc. Đối với điều này, chúng ta cần sử dụng hàm tạo Workbook ().
workbook = xlsxwriter.Workbook('report2.xlsx')
Bây giờ, hãy tạo một trang tính mới bằng cách sử dụng mô-đun add_worksheet ().
worksheet = workbook.add_worksheet()
Tiếp theo, ghi dữ liệu sau vào trang tính:
report2 = (['Ram', 32, ‘Bhopal’],['Mohan',25, ‘Chandigarh’] ,['Parkash',45, ‘Delhi’])
row = 0
col = 0
Bạn có thể lặp lại dữ liệu này và viết nó như sau:
for item, cost in (a):
worksheet.write(row, col, item)
worksheet.write(row, col+1, cost)
row + = 1
Bây giờ, chúng ta hãy đóng tệp Excel này bằng cách sử dụng phương thức close ().
workbook.close()
Tập lệnh trên sẽ tạo một tệp Excel có tên report2.xlsx có dữ liệu sau:
Ram | 32 | Bhopal |
Mohan | 25 | Chandigarh |
Parkash | 45 | Delhi |
Phương tiện thu thập điều tra
Điều quan trọng là điều tra viên phải có các ghi chép điều tra chi tiết để nhớ lại chính xác các phát hiện hoặc tập hợp tất cả các phần điều tra lại. Ảnh chụp màn hình rất hữu ích để theo dõi các bước được thực hiện cho một cuộc điều tra cụ thể. Với sự trợ giúp của mã Python sau, chúng ta có thể chụp ảnh màn hình và lưu nó trên đĩa cứng để sử dụng trong tương lai.
Trước tiên, cài đặt mô-đun Python có tên pyscreenshot bằng cách sử dụng lệnh sau:
Pip install pyscreenshot
Bây giờ, nhập các mô-đun cần thiết như được hiển thị -
import pyscreenshot as ImageGrab
Sử dụng dòng mã sau để lấy ảnh chụp màn hình -
image = ImageGrab.grab()
Sử dụng dòng mã sau để lưu ảnh chụp màn hình vào vị trí nhất định -
image.save('d:/image123.png')
Bây giờ, nếu bạn muốn hiển thị ảnh chụp màn hình dưới dạng đồ thị, bạn có thể sử dụng mã Python sau:
import numpy as np
import matplotlib.pyplot as plt
import pyscreenshot as ImageGrab
imageg = ImageGrab.grab()
plt.imshow(image, cmap='gray', interpolation='bilinear')
plt.show()
Chương này sẽ giải thích pháp y kỹ thuật số Python trên thiết bị di động và các khái niệm liên quan.
Giới thiệu
Pháp y thiết bị di động là nhánh của pháp y kỹ thuật số liên quan đến việc thu thập và phân tích các thiết bị di động để khôi phục bằng chứng kỹ thuật số mà điều tra quan tâm. Nhánh này khác với pháp y máy tính vì thiết bị di động có hệ thống liên lạc sẵn có rất hữu ích để cung cấp thông tin hữu ích liên quan đến vị trí.
Mặc dù việc sử dụng điện thoại thông minh ngày càng tăng trong pháp y kỹ thuật số, nhưng nó vẫn được coi là không đạt tiêu chuẩn do tính không đồng nhất của nó. Mặt khác, phần cứng máy tính, chẳng hạn như đĩa cứng, được coi là tiêu chuẩn và được phát triển như một kỷ luật ổn định. Trong ngành pháp y kỹ thuật số, có rất nhiều tranh luận về các kỹ thuật được sử dụng cho các thiết bị phi tiêu chuẩn, có bằng chứng thoáng qua, chẳng hạn như điện thoại thông minh.
Phần mềm có thể chiết xuất từ thiết bị di động
Các thiết bị di động hiện đại có rất nhiều thông tin kỹ thuật số so với các điện thoại cũ chỉ có nhật ký cuộc gọi hoặc tin nhắn SMS. Do đó, thiết bị di động có thể cung cấp cho các nhà điều tra rất nhiều thông tin chi tiết về người dùng của nó. Một số hiện vật có thể được trích xuất từ thiết bị di động như được đề cập bên dưới -
Messages - Đây là những hiện vật hữu ích có thể tiết lộ trạng thái tâm hồn của chủ sở hữu và thậm chí có thể cung cấp một số thông tin chưa biết trước đó cho người điều tra.
Location History- Dữ liệu lịch sử vị trí là một hiện vật hữu ích mà các nhà điều tra có thể sử dụng để xác thực về vị trí cụ thể của một người.
Applications Installed - Bằng cách truy cập vào loại ứng dụng được cài đặt, điều tra viên có được một số thông tin chi tiết về thói quen và suy nghĩ của người dùng di động.
Nguồn bằng chứng và xử lý bằng Python
Điện thoại thông minh có cơ sở dữ liệu SQLite và tệp PLIST là nguồn bằng chứng chính. Trong phần này, chúng tôi sẽ xử lý các nguồn bằng chứng trong python.
Phân tích tệp PLIST
PLIST (Danh sách tài sản) là một định dạng linh hoạt và thuận tiện để lưu trữ dữ liệu ứng dụng, đặc biệt là trên các thiết bị iPhone. Nó sử dụng phần mở rộng.plist. Loại tệp này được sử dụng để lưu trữ thông tin về các gói và ứng dụng. Nó có thể ở hai định dạng:XML và binary. Mã Python sau sẽ mở và đọc tệp PLIST. Lưu ý rằng trước khi tiếp tục việc này, chúng ta phải tạoInfo.plist tập tin.
Đầu tiên, hãy cài đặt thư viện của bên thứ ba có tên biplist bằng lệnh sau -
Pip install biplist
Bây giờ, hãy nhập một số thư viện hữu ích để xử lý tệp plist -
import biplist
import os
import sys
Bây giờ, sử dụng lệnh sau theo phương thức main có thể được sử dụng để đọc tệp plist thành một biến -
def main(plist):
try:
data = biplist.readPlist(plist)
except (biplist.InvalidPlistException,biplist.NotBinaryPlistException) as e:
print("[-] Invalid PLIST file - unable to be opened by biplist")
sys.exit(1)
Bây giờ, chúng ta có thể đọc dữ liệu trên bảng điều khiển hoặc in trực tiếp từ biến này.
Cơ sở dữ liệu SQLite
SQLite đóng vai trò là kho dữ liệu chính trên thiết bị di động. SQLite một thư viện trong quy trình triển khai một công cụ cơ sở dữ liệu SQL giao dịch độc lập, không cần máy chủ, không cấu hình bằng không. Nó là một cơ sở dữ liệu, được cấu hình bằng không, bạn không cần phải cấu hình nó trong hệ thống của mình, không giống như các cơ sở dữ liệu khác.
Nếu bạn là người mới làm quen hoặc chưa quen với cơ sở dữ liệu SQLite, bạn có thể theo liên kết www.tutorialspoint.com/sqlite/index.htm Ngoài ra, bạn có thể theo liên kết www.tutorialspoint.com/sqlite/sqlite_python.htm trong trường hợp bạn muốn tìm hiểu chi tiết về SQLite với Python.
Trong quá trình pháp y di động, chúng tôi có thể tương tác với sms.db tệp của thiết bị di động và có thể trích xuất thông tin có giá trị từ messagebàn. Python có một thư viện tích hợp có tênsqlite3để kết nối với cơ sở dữ liệu SQLite. Bạn có thể nhập tương tự bằng lệnh sau:
import sqlite3
Bây giờ, với sự trợ giúp của lệnh sau, chúng tôi có thể kết nối với cơ sở dữ liệu, nói sms.db trong trường hợp thiết bị di động -
Conn = sqlite3.connect(‘sms.db’)
C = conn.cursor()
Ở đây, C là đối tượng con trỏ với sự trợ giúp mà chúng ta có thể tương tác với cơ sở dữ liệu.
Bây giờ, giả sử nếu chúng ta muốn thực hiện một lệnh cụ thể, hãy nói để lấy chi tiết từ abc table, nó có thể được thực hiện với sự trợ giúp của lệnh sau:
c.execute(“Select * from abc”)
c.close()
Kết quả của lệnh trên sẽ được lưu trữ trong cursorvật. Tương tự, chúng ta có thể sử dụngfetchall() phương thức để kết xuất kết quả vào một biến mà chúng ta có thể thao tác.
Chúng ta có thể sử dụng lệnh sau để lấy dữ liệu tên cột của bảng thông báo trong sms.db -
c.execute(“pragma table_info(message)”)
table_data = c.fetchall()
columns = [x[1] for x in table_data
Hãy quan sát rằng ở đây chúng ta đang sử dụng lệnh SQLite PRAGMA là lệnh đặc biệt được sử dụng để điều khiển các biến môi trường và cờ trạng thái khác nhau trong môi trường SQLite. Trong lệnh trên,fetchall()phương thức trả về nhiều kết quả. Tên của mỗi cột được lưu trữ trong chỉ mục đầu tiên của mỗi bộ.
Bây giờ, với sự trợ giúp của lệnh sau, chúng ta có thể truy vấn bảng cho tất cả dữ liệu của nó và lưu trữ nó trong biến có tên data_msg -
c.execute(“Select * from message”)
data_msg = c.fetchall()
Lệnh trên sẽ lưu trữ dữ liệu trong biến và hơn nữa chúng ta cũng có thể ghi dữ liệu trên vào tệp CSV bằng cách sử dụng csv.writer() phương pháp.
Sao lưu iTunes
Pháp y điện thoại di động iPhone có thể được thực hiện trên các bản sao lưu do iTunes tạo. Các giám định viên pháp y dựa vào việc phân tích các bản sao lưu logic của iPhone có được thông qua iTunes. Giao thức AFC (kết nối tệp của Apple) được iTunes sử dụng để sao lưu. Bên cạnh đó, quá trình sao lưu không sửa đổi bất cứ điều gì trên iPhone ngoại trừ các bản ghi khóa ký quỹ.
Bây giờ, câu hỏi đặt ra là tại sao điều quan trọng đối với một chuyên gia pháp y kỹ thuật số là phải hiểu các kỹ thuật sao lưu iTunes? Điều quan trọng là chúng ta có thể truy cập trực tiếp vào máy tính của nghi phạm thay vì iPhone vì khi máy tính được sử dụng để đồng bộ hóa với iPhone, thì hầu hết thông tin trên iPhone có khả năng được sao lưu trên máy tính.
Quy trình sao lưu và vị trí của nó
Bất cứ khi nào một sản phẩm của Apple được sao lưu vào máy tính, sản phẩm đó sẽ đồng bộ với iTunes và sẽ có một thư mục cụ thể với ID duy nhất của thiết bị. Ở định dạng sao lưu mới nhất, các tệp được lưu trữ trong các thư mục con chứa hai ký tự thập lục phân đầu tiên của tên tệp. Từ các tệp sao lưu này, có một số tệp như info.plist rất hữu ích cùng với cơ sở dữ liệu có tên Manifest.db. Bảng sau đây cho thấy các vị trí sao lưu, thay đổi theo hệ điều hành của bản sao lưu iTunes -
Hệ điều hành | Vị trí dự phòng |
---|---|
Win7 | C: \ Users \ [tên người dùng] \ AppData \ Roaming \ AppleComputer \ MobileSync \ Backup \ |
MAC OS X | ~ / Library / Application Suport / MobileSync / Backup / |
Để xử lý bản sao lưu iTunes bằng Python, trước tiên chúng ta cần xác định tất cả các bản sao lưu ở vị trí sao lưu theo hệ điều hành của chúng ta. Sau đó, chúng tôi sẽ lặp qua từng bản sao lưu và đọc cơ sở dữ liệu Manifest.db.
Bây giờ, với sự trợ giúp của mã Python sau, chúng ta có thể làm tương tự -
Đầu tiên, nhập các thư viện cần thiết như sau:
from __future__ import print_function
import argparse
import logging
import os
from shutil import copyfile
import sqlite3
import sys
logger = logging.getLogger(__name__)
Bây giờ, cung cấp hai đối số vị trí là INPUT_DIR và OUTPUT_DIR đại diện cho bản sao lưu iTunes và thư mục đầu ra mong muốn -
if __name__ == "__main__":
parser.add_argument("INPUT_DIR",help = "Location of folder containing iOS backups, ""e.g. ~\Library\Application Support\MobileSync\Backup folder")
parser.add_argument("OUTPUT_DIR", help = "Output Directory")
parser.add_argument("-l", help = "Log file path",default = __file__[:-2] + "log")
parser.add_argument("-v", help = "Increase verbosity",action = "store_true") args = parser.parse_args()
Bây giờ, thiết lập nhật ký như sau:
if args.v:
logger.setLevel(logging.DEBUG)
else:
logger.setLevel(logging.INFO)
Bây giờ, hãy thiết lập định dạng thông báo cho nhật ký này như sau:
msg_fmt = logging.Formatter("%(asctime)-15s %(funcName)-13s""%(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 iBackup Visualizer")
logger.debug("Supplied arguments: {}".format(" ".join(sys.argv[1:])))
logger.debug("System: " + sys.platform)
logger.debug("Python Version: " + sys.version)
Dòng mã sau sẽ tạo các thư mục cần thiết cho thư mục đầu ra mong muốn bằng cách sử dụng os.makedirs() chức năng -
if not os.path.exists(args.OUTPUT_DIR):
os.makedirs(args.OUTPUT_DIR)
Bây giờ, chuyển các thư mục đầu vào và đầu ra được cung cấp cho hàm main () như sau:
if os.path.exists(args.INPUT_DIR) and os.path.isdir(args.INPUT_DIR):
main(args.INPUT_DIR, args.OUTPUT_DIR)
else:
logger.error("Supplied input directory does not exist or is not ""a directory")
sys.exit(1)
Bây giờ viết main() chức năng sẽ gọi thêm backup_summary() chức năng xác định tất cả các bản sao lưu có trong thư mục đầu vào -
def main(in_dir, out_dir):
backups = backup_summary(in_dir)
def backup_summary(in_dir):
logger.info("Identifying all iOS backups in {}".format(in_dir))
root = os.listdir(in_dir)
backups = {}
for x in root:
temp_dir = os.path.join(in_dir, x)
if os.path.isdir(temp_dir) and len(x) == 40:
num_files = 0
size = 0
for root, subdir, files in os.walk(temp_dir):
num_files += len(files)
size += sum(os.path.getsize(os.path.join(root, name))
for name in files)
backups[x] = [temp_dir, num_files, size]
return backups
Bây giờ, in bản tóm tắt của mỗi bản sao lưu vào bảng điều khiển như sau:
print("Backup Summary")
print("=" * 20)
if len(backups) > 0:
for i, b in enumerate(backups):
print("Backup No.: {} \n""Backup Dev. Name: {} \n""# Files: {} \n""Backup Size (Bytes): {}\n".format(i, b, backups[b][1], backups[b][2]))
Bây giờ, hãy kết xuất nội dung của tệp Manifest.db vào biến có tên db_items.
try:
db_items = process_manifest(backups[b][0])
except IOError:
logger.warn("Non-iOS 10 backup encountered or " "invalid backup. Continuing to next backup.")
continue
Bây giờ, chúng ta hãy xác định một hàm sẽ lấy đường dẫn thư mục của bản sao lưu -
def process_manifest(backup):
manifest = os.path.join(backup, "Manifest.db")
if not os.path.exists(manifest):
logger.error("Manifest DB not found in {}".format(manifest))
raise IOError
Bây giờ, sử dụng SQLite3, chúng tôi sẽ kết nối với cơ sở dữ liệu bằng con trỏ có tên là c -
c = conn.cursor()
items = {}
for row in c.execute("SELECT * from Files;"):
items[row[0]] = [row[2], row[1], row[3]]
return items
create_files(in_dir, out_dir, b, db_items)
print("=" * 20)
else:
logger.warning("No valid backups found. The input directory should be
" "the parent-directory immediately above the SHA-1 hash " "iOS device backups")
sys.exit(2)
Bây giờ, xác định create_files() phương pháp như sau -
def create_files(in_dir, out_dir, b, db_items):
msg = "Copying Files for backup {} to {}".format(b, os.path.join(out_dir, b))
logger.info(msg)
Bây giờ, hãy lặp lại từng khóa trong db_items từ điển -
for x, key in enumerate(db_items):
if db_items[key][0] is None or db_items[key][0] == "":
continue
else:
dirpath = os.path.join(out_dir, b,
os.path.dirname(db_items[key][0]))
filepath = os.path.join(out_dir, b, db_items[key][0])
if not os.path.exists(dirpath):
os.makedirs(dirpath)
original_dir = b + "/" + key[0:2] + "/" + key
path = os.path.join(in_dir, original_dir)
if os.path.exists(filepath):
filepath = filepath + "_{}".format(x)
Bây giờ, sử dụng shutil.copyfile() phương pháp sao chép tệp đã sao lưu như sau:
try:
copyfile(path, filepath)
except IOError:
logger.debug("File not found in backup: {}".format(path))
files_not_found += 1
if files_not_found > 0:
logger.warning("{} files listed in the Manifest.db not" "found in
backup".format(files_not_found))
copyfile(os.path.join(in_dir, b, "Info.plist"), os.path.join(out_dir, b,
"Info.plist"))
copyfile(os.path.join(in_dir, b, "Manifest.db"), os.path.join(out_dir, b,
"Manifest.db"))
copyfile(os.path.join(in_dir, b, "Manifest.plist"), os.path.join(out_dir, b,
"Manifest.plist"))
copyfile(os.path.join(in_dir, b, "Status.plist"),os.path.join(out_dir, b,
"Status.plist"))
Với tập lệnh Python ở trên, chúng ta có thể nhận cấu trúc tệp sao lưu được cập nhật trong thư mục đầu ra của chúng ta. Chúng ta có thể sử dụngpycrypto thư viện python để giải mã các bản sao lưu.
Wifi
Thiết bị di động có thể được sử dụng để kết nối với thế giới bên ngoài bằng cách kết nối thông qua mạng Wi-Fi có sẵn ở khắp mọi nơi. Đôi khi thiết bị được kết nối tự động với các mạng mở này.
Trong trường hợp iPhone, danh sách các kết nối Wi-Fi đang mở mà thiết bị đã kết nối được lưu trữ trong một tệp PLIST có tên com.apple.wifi.plist. Tệp này sẽ chứa Wi-Fi SSID, BSSID và thời gian kết nối.
Chúng tôi cần trích xuất chi tiết Wi-Fi từ báo cáo Cellebrite XML chuẩn bằng Python. Đối với điều này, chúng tôi cần sử dụng API từ Công cụ ghi nhật ký địa lý không dây (WIGLE), một nền tảng phổ biến có thể được sử dụng để tìm vị trí của thiết bị bằng cách sử dụng tên của mạng Wi-Fi.
Chúng ta có thể sử dụng thư viện Python có tên requestsđể truy cập API từ WIGLE. Nó có thể được cài đặt như sau:
pip install requests
API từ WIGLE
Chúng tôi cần đăng ký trên trang web của WIGLE https://wigle.net/accountđể nhận API miễn phí từ WIGLE. Tập lệnh Python để lấy thông tin về thiết bị người dùng và kết nối của nó thông qua API của WIGEL được thảo luận bên dưới:
Đầu tiên, nhập các thư viện sau để xử lý những thứ khác nhau -
from __future__ import print_function
import argparse
import csv
import os
import sys
import xml.etree.ElementTree as ET
import requests
Bây giờ, cung cấp hai đối số vị trí cụ thể là INPUT_FILE và OUTPUT_CSV sẽ đại diện cho tệp đầu vào có địa chỉ MAC Wi-Fi và tệp CSV đầu ra mong muốn tương ứng -
if __name__ == "__main__":
parser.add_argument("INPUT_FILE", help = "INPUT FILE with MAC Addresses")
parser.add_argument("OUTPUT_CSV", help = "Output CSV File")
parser.add_argument("-t", help = "Input type: Cellebrite XML report or TXT
file",choices = ('xml', 'txt'), default = "xml")
parser.add_argument('--api', help = "Path to API key
file",default = os.path.expanduser("~/.wigle_api"),
type = argparse.FileType('r'))
args = parser.parse_args()
Bây giờ các dòng mã sau sẽ kiểm tra xem tệp đầu vào có tồn tại và là tệp hay không. Nếu không, nó sẽ thoát khỏi tập lệnh -
if not os.path.exists(args.INPUT_FILE) or \ not os.path.isfile(args.INPUT_FILE):
print("[-] {} does not exist or is not a
file".format(args.INPUT_FILE))
sys.exit(1)
directory = os.path.dirname(args.OUTPUT_CSV)
if directory != '' and not os.path.exists(directory):
os.makedirs(directory)
api_key = args.api.readline().strip().split(":")
Bây giờ, chuyển đối số vào main như sau:
main(args.INPUT_FILE, args.OUTPUT_CSV, args.t, api_key)
def main(in_file, out_csv, type, api_key):
if type == 'xml':
wifi = parse_xml(in_file)
else:
wifi = parse_txt(in_file)
query_wigle(wifi, out_csv, api_key)
Bây giờ, chúng ta sẽ phân tích cú pháp tệp XML như sau:
def parse_xml(xml_file):
wifi = {}
xmlns = "{http://pa.cellebrite.com/report/2.0}"
print("[+] Opening {} report".format(xml_file))
xml_tree = ET.parse(xml_file)
print("[+] Parsing report for all connected WiFi addresses")
root = xml_tree.getroot()
Bây giờ, hãy lặp lại phần tử con của root như sau:
for child in root.iter():
if child.tag == xmlns + "model":
if child.get("type") == "Location":
for field in child.findall(xmlns + "field"):
if field.get("name") == "TimeStamp":
ts_value = field.find(xmlns + "value")
try:
ts = ts_value.text
except AttributeError:
continue
Bây giờ, chúng tôi sẽ kiểm tra xem chuỗi 'ssid' có trong văn bản của giá trị hay không -
if "SSID" in value.text:
bssid, ssid = value.text.split("\t")
bssid = bssid[7:]
ssid = ssid[6:]
Bây giờ, chúng ta cần thêm BSSID, SSID và dấu thời gian vào từ điển wifi như sau:
if bssid in wifi.keys():
wifi[bssid]["Timestamps"].append(ts)
wifi[bssid]["SSID"].append(ssid)
else:
wifi[bssid] = {"Timestamps": [ts], "SSID":
[ssid],"Wigle": {}}
return wifi
Trình phân tích cú pháp văn bản đơn giản hơn nhiều mà trình phân tích cú pháp XML được hiển thị bên dưới:
def parse_txt(txt_file):
wifi = {}
print("[+] Extracting MAC addresses from {}".format(txt_file))
with open(txt_file) as mac_file:
for line in mac_file:
wifi[line.strip()] = {"Timestamps": ["N/A"], "SSID":
["N/A"],"Wigle": {}}
return wifi
Bây giờ, chúng ta hãy sử dụng mô-đun yêu cầu để thực hiện WIGLE APIcuộc gọi và cần chuyển sang query_wigle() phương pháp -
def query_wigle(wifi_dictionary, out_csv, api_key):
print("[+] Querying Wigle.net through Python API for {} "
"APs".format(len(wifi_dictionary)))
for mac in wifi_dictionary:
wigle_results = query_mac_addr(mac, api_key)
def query_mac_addr(mac_addr, api_key):
query_url = "https://api.wigle.net/api/v2/network/search?" \
"onlymine = false&freenet = false&paynet = false" \ "&netid = {}".format(mac_addr)
req = requests.get(query_url, auth = (api_key[0], api_key[1]))
return req.json()
Trên thực tế, có một giới hạn mỗi ngày cho các lệnh gọi API WIGLE, nếu vượt quá giới hạn đó thì nó phải hiển thị lỗi như sau:
try:
if wigle_results["resultCount"] == 0:
wifi_dictionary[mac]["Wigle"]["results"] = []
continue
else:
wifi_dictionary[mac]["Wigle"] = wigle_results
except KeyError:
if wigle_results["error"] == "too many queries today":
print("[-] Wigle daily query limit exceeded")
wifi_dictionary[mac]["Wigle"]["results"] = []
continue
else:
print("[-] Other error encountered for " "address {}: {}".format(mac,
wigle_results['error']))
wifi_dictionary[mac]["Wigle"]["results"] = []
continue
prep_output(out_csv, wifi_dictionary)
Bây giờ, chúng ta sẽ sử dụng prep_output() phương pháp làm phẳng từ điển thành các phần có thể ghi dễ dàng -
def prep_output(output, data):
csv_data = {}
google_map = https://www.google.com/maps/search/
Bây giờ, hãy truy cập tất cả dữ liệu chúng tôi đã thu thập được cho đến nay như sau:
for x, mac in enumerate(data):
for y, ts in enumerate(data[mac]["Timestamps"]):
for z, result in enumerate(data[mac]["Wigle"]["results"]):
shortres = data[mac]["Wigle"]["results"][z]
g_map_url = "{}{},{}".format(google_map, shortres["trilat"],shortres["trilong"])
Bây giờ, chúng ta có thể viết đầu ra trong tệp CSV như chúng ta đã thực hiện trong các tập lệnh trước đó trong chương này bằng cách sử dụng write_csv() chức năng.
Trong chương này, chúng ta sẽ tìm hiểu chi tiết về cách điều tra siêu dữ liệu nhúng bằng pháp y kỹ thuật số Python.
Giới thiệu
Siêu dữ liệu được nhúng là thông tin về dữ liệu được lưu trữ trong cùng một tệp có đối tượng được mô tả bởi dữ liệu đó. Nói cách khác, đó là thông tin về tài sản kỹ thuật số được lưu trữ trong chính tệp kỹ thuật số. Nó luôn được liên kết với tệp và không bao giờ có thể tách rời.
Trong trường hợp pháp y kỹ thuật số, chúng tôi không thể trích xuất tất cả thông tin về một tệp cụ thể. Mặt khác, siêu dữ liệu được nhúng có thể cung cấp cho chúng tôi thông tin quan trọng đối với cuộc điều tra. Ví dụ: siêu dữ liệu của tệp văn bản có thể chứa thông tin về tác giả, độ dài, ngày viết và thậm chí là một bản tóm tắt ngắn về tài liệu đó. Hình ảnh kỹ thuật số có thể bao gồm siêu dữ liệu như độ dài của hình ảnh, tốc độ cửa trập, v.v.
Phần mềm có chứa thuộc tính siêu dữ liệu và phần trích xuất của chúng
Trong phần này, chúng ta sẽ tìm hiểu về các tạo tác khác nhau chứa các thuộc tính siêu dữ liệu và quy trình trích xuất của chúng bằng Python.
Âm thanh và video
Đây là hai tạo tác rất phổ biến có siêu dữ liệu được nhúng. Siêu dữ liệu này có thể được trích xuất cho mục đích điều tra.
Bạn có thể sử dụng tập lệnh Python sau để trích xuất các thuộc tính hoặc siêu dữ liệu phổ biến từ tệp âm thanh hoặc MP3 và video hoặc tệp MP4.
Lưu ý rằng đối với tập lệnh này, chúng tôi cần cài đặt thư viện python của bên thứ ba có tên là mutagen cho phép chúng tôi trích xuất siêu dữ liệu từ các tệp âm thanh và video. Nó có thể được cài đặt với sự trợ giúp của lệnh sau:
pip install mutagen
Một số thư viện hữu ích mà chúng ta cần nhập cho tập lệnh Python này như sau:
from __future__ import print_function
import argparse
import json
import mutagen
Trình xử lý dòng lệnh sẽ nhận một đối số đại diện cho đường dẫn đến tệp MP3 hoặc MP4. Sau đó, chúng tôi sẽ sử dụngmutagen.file() để mở một xử lý tệp như sau:
if __name__ == '__main__':
parser = argparse.ArgumentParser('Python Metadata Extractor')
parser.add_argument("AV_FILE", help="File to extract metadata from")
args = parser.parse_args()
av_file = mutagen.File(args.AV_FILE)
file_ext = args.AV_FILE.rsplit('.', 1)[-1]
if file_ext.lower() == 'mp3':
handle_id3(av_file)
elif file_ext.lower() == 'mp4':
handle_mp4(av_file)
Bây giờ, chúng ta cần sử dụng hai tay cầm, một để trích xuất dữ liệu từ MP3 và một để trích xuất dữ liệu từ tệp MP4. Chúng ta có thể xác định các chốt này như sau:
def handle_id3(id3_file):
id3_frames = {'TIT2': 'Title', 'TPE1': 'Artist', 'TALB': 'Album','TXXX':
'Custom', 'TCON': 'Content Type', 'TDRL': 'Date released','COMM': 'Comments',
'TDRC': 'Recording Date'}
print("{:15} | {:15} | {:38} | {}".format("Frame", "Description","Text","Value"))
print("-" * 85)
for frames in id3_file.tags.values():
frame_name = id3_frames.get(frames.FrameID, frames.FrameID)
desc = getattr(frames, 'desc', "N/A")
text = getattr(frames, 'text', ["N/A"])[0]
value = getattr(frames, 'value', "N/A")
if "date" in frame_name.lower():
text = str(text)
print("{:15} | {:15} | {:38} | {}".format(
frame_name, desc, text, value))
def handle_mp4(mp4_file):
cp_sym = u"\u00A9"
qt_tag = {
cp_sym + 'nam': 'Title', cp_sym + 'art': 'Artist',
cp_sym + 'alb': 'Album', cp_sym + 'gen': 'Genre',
'cpil': 'Compilation', cp_sym + 'day': 'Creation Date',
'cnID': 'Apple Store Content ID', 'atID': 'Album Title ID',
'plID': 'Playlist ID', 'geID': 'Genre ID', 'pcst': 'Podcast',
'purl': 'Podcast URL', 'egid': 'Episode Global ID',
'cmID': 'Camera ID', 'sfID': 'Apple Store Country',
'desc': 'Description', 'ldes': 'Long Description'}
genre_ids = json.load(open('apple_genres.json'))
Bây giờ, chúng ta cần lặp qua tệp MP4 này như sau:
print("{:22} | {}".format('Name', 'Value'))
print("-" * 40)
for name, value in mp4_file.tags.items():
tag_name = qt_tag.get(name, name)
if isinstance(value, list):
value = "; ".join([str(x) for x in value])
if name == 'geID':
value = "{}: {}".format(
value, genre_ids[str(value)].replace("|", " - "))
print("{:22} | {}".format(tag_name, value))
Tập lệnh trên sẽ cung cấp cho chúng ta thông tin bổ sung về tệp MP3 cũng như MP4.
Hình ảnh
Hình ảnh có thể chứa các loại siêu dữ liệu khác nhau tùy thuộc vào định dạng tệp của nó. Tuy nhiên, hầu hết các hình ảnh đều nhúng thông tin GPS. Chúng tôi có thể trích xuất thông tin GPS này bằng cách sử dụng các thư viện Python của bên thứ ba. Bạn có thể sử dụng tập lệnh Python sau có thể được sử dụng để làm điều tương tự:
Đầu tiên, tải xuống thư viện python của bên thứ ba có tên Python Imaging Library (PIL) như sau -
pip install pillow
Điều này sẽ giúp chúng tôi trích xuất siêu dữ liệu từ hình ảnh.
Chúng tôi cũng có thể ghi chi tiết GPS được nhúng trong hình ảnh vào tệp KML, nhưng để làm điều này, chúng tôi cần tải xuống thư viện Python của bên thứ ba có tên simplekml như sau -
pip install simplekml
Trong tập lệnh này, trước tiên chúng ta cần nhập các thư viện sau:
from __future__ import print_function
import argparse
from PIL import Image
from PIL.ExifTags import TAGS
import simplekml
import sys
Bây giờ, trình xử lý dòng lệnh sẽ chấp nhận một đối số vị trí về cơ bản đại diện cho đường dẫn tệp của ảnh.
parser = argparse.ArgumentParser('Metadata from images')
parser.add_argument('PICTURE_FILE', help = "Path to picture")
args = parser.parse_args()
Bây giờ, chúng ta cần chỉ định các URL sẽ điền thông tin tọa độ. Các URL làgmaps và open_maps. Chúng ta cũng cần một hàm để chuyển đổi tọa độ tuple độ phút giây (DMS), được cung cấp bởi thư viện PIL, thành số thập phân. Nó có thể được thực hiện như sau:
gmaps = "https://www.google.com/maps?q={},{}"
open_maps = "http://www.openstreetmap.org/?mlat={}&mlon={}"
def process_coords(coord):
coord_deg = 0
for count, values in enumerate(coord):
coord_deg += (float(values[0]) / values[1]) / 60**count
return coord_deg
Bây giờ, chúng ta sẽ sử dụng image.open() để mở tệp dưới dạng đối tượng PIL.
img_file = Image.open(args.PICTURE_FILE)
exif_data = img_file._getexif()
if exif_data is None:
print("No EXIF data found")
sys.exit()
for name, value in exif_data.items():
gps_tag = TAGS.get(name, name)
if gps_tag is not 'GPSInfo':
continue
Sau khi tìm thấy GPSInfo , chúng tôi sẽ lưu trữ tham chiếu GPS và xử lý các tọa độ với process_coords() phương pháp.
lat_ref = value[1] == u'N'
lat = process_coords(value[2])
if not lat_ref:
lat = lat * -1
lon_ref = value[3] == u'E'
lon = process_coords(value[4])
if not lon_ref:
lon = lon * -1
Bây giờ, bắt đầu kml đối tượng từ simplekml thư viện như sau -
kml = simplekml.Kml()
kml.newpoint(name = args.PICTURE_FILE, coords = [(lon, lat)])
kml.save(args.PICTURE_FILE + ".kml")
Bây giờ chúng ta có thể in tọa độ từ thông tin đã xử lý như sau:
print("GPS Coordinates: {}, {}".format(lat, lon))
print("Google Maps URL: {}".format(gmaps.format(lat, lon)))
print("OpenStreetMap URL: {}".format(open_maps.format(lat, lon)))
print("KML File {} created".format(args.PICTURE_FILE + ".kml"))
Tài liệu PDF
Tài liệu PDF có nhiều phương tiện bao gồm hình ảnh, văn bản, biểu mẫu, v.v. Khi chúng tôi trích xuất siêu dữ liệu được nhúng trong tài liệu PDF, chúng tôi có thể nhận được dữ liệu kết quả ở định dạng được gọi là Nền tảng siêu dữ liệu mở rộng (XMP). Chúng tôi có thể trích xuất siêu dữ liệu với sự trợ giúp của mã Python sau:
Đầu tiên, hãy cài đặt thư viện Python của bên thứ ba có tên PyPDF2để đọc siêu dữ liệu được lưu trữ ở định dạng XMP. Nó có thể được cài đặt như sau:
pip install PyPDF2
Bây giờ, hãy nhập các thư viện sau để trích xuất siêu dữ liệu từ các tệp PDF -
from __future__ import print_function
from argparse import ArgumentParser, FileType
import datetime
from PyPDF2 import PdfFileReader
import sys
Bây giờ, trình xử lý dòng lệnh sẽ chấp nhận một đối số vị trí về cơ bản đại diện cho đường dẫn tệp của tệp PDF.
parser = argparse.ArgumentParser('Metadata from PDF')
parser.add_argument('PDF_FILE', help='Path to PDF file',type=FileType('rb'))
args = parser.parse_args()
Bây giờ chúng ta có thể sử dụng getXmpMetadata() để cung cấp một đối tượng chứa siêu dữ liệu có sẵn như sau:
pdf_file = PdfFileReader(args.PDF_FILE)
xmpm = pdf_file.getXmpMetadata()
if xmpm is None:
print("No XMP metadata found in document.")
sys.exit()
Chúng ta có thể sử dụng custom_print() phương pháp để trích xuất và in các giá trị có liên quan như tiêu đề, người tạo, người đóng góp, v.v. như sau:
custom_print("Title: {}", xmpm.dc_title)
custom_print("Creator(s): {}", xmpm.dc_creator)
custom_print("Contributors: {}", xmpm.dc_contributor)
custom_print("Subject: {}", xmpm.dc_subject)
custom_print("Description: {}", xmpm.dc_description)
custom_print("Created: {}", xmpm.xmp_createDate)
custom_print("Modified: {}", xmpm.xmp_modifyDate)
custom_print("Event Dates: {}", xmpm.dc_date)
Chúng tôi cũng có thể xác định custom_print() trong trường hợp nếu PDF được tạo bằng nhiều phần mềm như sau:
def custom_print(fmt_str, value):
if isinstance(value, list):
print(fmt_str.format(", ".join(value)))
elif isinstance(value, dict):
fmt_value = [":".join((k, v)) for k, v in value.items()]
print(fmt_str.format(", ".join(value)))
elif isinstance(value, str) or isinstance(value, bool):
print(fmt_str.format(value))
elif isinstance(value, bytes):
print(fmt_str.format(value.decode()))
elif isinstance(value, datetime.datetime):
print(fmt_str.format(value.isoformat()))
elif value is None:
print(fmt_str.format("N/A"))
else:
print("warn: unhandled type {} found".format(type(value)))
Chúng tôi cũng có thể trích xuất bất kỳ thuộc tính tùy chỉnh nào khác được phần mềm lưu như sau:
if xmpm.custom_properties:
print("Custom Properties:")
for k, v in xmpm.custom_properties.items():
print("\t{}: {}".format(k, v))
Tập lệnh trên sẽ đọc tài liệu PDF và sẽ in siêu dữ liệu được lưu trữ ở định dạng XMP bao gồm một số thuộc tính tùy chỉnh được phần mềm lưu trữ với sự trợ giúp của tệp PDF đó.
Tệp Windows Executable
Đôi khi chúng tôi có thể gặp phải một tệp thực thi đáng ngờ hoặc trái phép. Nhưng đối với mục đích điều tra, nó có thể hữu ích vì siêu dữ liệu được nhúng. Chúng ta có thể lấy thông tin như vị trí, mục đích của nó và các thuộc tính khác như nhà sản xuất, ngày biên dịch, v.v. Với sự trợ giúp của tập lệnh Python sau, chúng ta có thể lấy ngày biên dịch, dữ liệu hữu ích từ các tiêu đề và các ký hiệu được nhập cũng như xuất.
Với mục đích này, trước tiên hãy cài đặt thư viện Python của bên thứ ba pefile. Nó có thể được thực hiện như sau:
pip install pefile
Khi bạn cài đặt thành công phần mềm này, hãy nhập các thư viện sau như sau:
from __future__ import print_function
import argparse
from datetime import datetime
from pefile import PE
Bây giờ, trình xử lý dòng lệnh sẽ chấp nhận một đối số vị trí về cơ bản đại diện cho đường dẫn tệp của tệp thực thi. Bạn cũng có thể chọn kiểu đầu ra, cho dù bạn cần nó một cách chi tiết và dài dòng hay một cách đơn giản. Đối với điều này, bạn cần đưa ra một đối số tùy chọn như hình dưới đây:
parser = argparse.ArgumentParser('Metadata from executable file')
parser.add_argument("EXE_FILE", help = "Path to exe file")
parser.add_argument("-v", "--verbose", help = "Increase verbosity of output",
action = 'store_true', default = False)
args = parser.parse_args()
Bây giờ, chúng ta sẽ tải tệp thực thi đầu vào bằng cách sử dụng lớp PE. Chúng tôi cũng sẽ kết xuất dữ liệu thực thi vào một đối tượng từ điển bằng cách sử dụngdump_dict() phương pháp.
pe = PE(args.EXE_FILE)
ped = pe.dump_dict()
Chúng tôi có thể trích xuất siêu dữ liệu tệp cơ bản như quyền tác giả được nhúng, phiên bản và thời gian biên dịch bằng cách sử dụng mã hiển thị bên dưới:
file_info = {}
for structure in pe.FileInfo:
if structure.Key == b'StringFileInfo':
for s_table in structure.StringTable:
for key, value in s_table.entries.items():
if value is None or len(value) == 0:
value = "Unknown"
file_info[key] = value
print("File Information: ")
print("==================")
for k, v in file_info.items():
if isinstance(k, bytes):
k = k.decode()
if isinstance(v, bytes):
v = v.decode()
print("{}: {}".format(k, v))
comp_time = ped['FILE_HEADER']['TimeDateStamp']['Value']
comp_time = comp_time.split("[")[-1].strip("]")
time_stamp, timezone = comp_time.rsplit(" ", 1)
comp_time = datetime.strptime(time_stamp, "%a %b %d %H:%M:%S %Y")
print("Compiled on {} {}".format(comp_time, timezone.strip()))
Chúng tôi có thể trích xuất dữ liệu hữu ích từ các tiêu đề như sau:
for section in ped['PE Sections']:
print("Section '{}' at {}: {}/{} {}".format(
section['Name']['Value'], hex(section['VirtualAddress']['Value']),
section['Misc_VirtualSize']['Value'],
section['SizeOfRawData']['Value'], section['MD5'])
)
Bây giờ, trích xuất danh sách các lần nhập và xuất từ các tệp thực thi như hình dưới đây -
if hasattr(pe, 'DIRECTORY_ENTRY_IMPORT'):
print("\nImports: ")
print("=========")
for dir_entry in pe.DIRECTORY_ENTRY_IMPORT:
dll = dir_entry.dll
if not args.verbose:
print(dll.decode(), end=", ")
continue
name_list = []
for impts in dir_entry.imports:
if getattr(impts, "name", b"Unknown") is None:
name = b"Unknown"
else:
name = getattr(impts, "name", b"Unknown")
name_list.append([name.decode(), hex(impts.address)])
name_fmt = ["{} ({})".format(x[0], x[1]) for x in name_list]
print('- {}: {}'.format(dll.decode(), ", ".join(name_fmt)))
if not args.verbose:
print()
Bây giờ, in exports, names và addresses sử dụng mã như hình dưới đây -
if hasattr(pe, 'DIRECTORY_ENTRY_EXPORT'):
print("\nExports: ")
print("=========")
for sym in pe.DIRECTORY_ENTRY_EXPORT.symbols:
print('- {}: {}'.format(sym.name.decode(), hex(sym.address)))
Tập lệnh trên sẽ trích xuất siêu dữ liệu cơ bản, thông tin từ tiêu đề từ các tệp thực thi của windows.
Siêu dữ liệu tài liệu Office
Hầu hết các công việc trong máy tính được thực hiện trong ba ứng dụng của MS Office - Word, PowerPoint và Excel. Các tệp này sở hữu siêu dữ liệu khổng lồ, có thể tiết lộ thông tin thú vị về quyền tác giả và lịch sử của chúng.
Lưu ý rằng siêu dữ liệu từ năm 2007 có định dạng word (.docx), excel (.xlsx) và powerpoint (.pptx) được lưu trữ trong một tệp XML. Chúng tôi có thể xử lý các tệp XML này bằng Python với sự trợ giúp của tập lệnh Python sau được hiển thị bên dưới:
Đầu tiên, nhập các thư viện bắt buộc như hình dưới đây -
from __future__ import print_function
from argparse import ArgumentParser
from datetime import datetime as dt
from xml.etree import ElementTree as etree
import zipfile
parser = argparse.ArgumentParser('Office Document Metadata’)
parser.add_argument("Office_File", help="Path to office file to read")
args = parser.parse_args()
Bây giờ, hãy kiểm tra xem tệp có phải là tệp ZIP hay không. Khác, nêu ra một lỗi. Bây giờ, hãy mở tệp và trích xuất các phần tử quan trọng để xử lý bằng đoạn mã sau:
zipfile.is_zipfile(args.Office_File)
zfile = zipfile.ZipFile(args.Office_File)
core_xml = etree.fromstring(zfile.read('docProps/core.xml'))
app_xml = etree.fromstring(zfile.read('docProps/app.xml'))
Bây giờ, hãy tạo một từ điển để bắt đầu trích xuất siêu dữ liệu -
core_mapping = {
'title': 'Title',
'subject': 'Subject',
'creator': 'Author(s)',
'keywords': 'Keywords',
'description': 'Description',
'lastModifiedBy': 'Last Modified By',
'modified': 'Modified Date',
'created': 'Created Date',
'category': 'Category',
'contentStatus': 'Status',
'revision': 'Revision'
}
Sử dụng iterchildren() để truy cập từng thẻ trong tệp XML -
for element in core_xml.getchildren():
for key, title in core_mapping.items():
if key in element.tag:
if 'date' in title.lower():
text = dt.strptime(element.text, "%Y-%m-%dT%H:%M:%SZ")
else:
text = element.text
print("{}: {}".format(title, text))
Tương tự, hãy làm điều này đối với tệp app.xml chứa thông tin thống kê về nội dung của tài liệu -
app_mapping = {
'TotalTime': 'Edit Time (minutes)',
'Pages': 'Page Count',
'Words': 'Word Count',
'Characters': 'Character Count',
'Lines': 'Line Count',
'Paragraphs': 'Paragraph Count',
'Company': 'Company',
'HyperlinkBase': 'Hyperlink Base',
'Slides': 'Slide count',
'Notes': 'Note Count',
'HiddenSlides': 'Hidden Slide Count',
}
for element in app_xml.getchildren():
for key, title in app_mapping.items():
if key in element.tag:
if 'date' in title.lower():
text = dt.strptime(element.text, "%Y-%m-%dT%H:%M:%SZ")
else:
text = element.text
print("{}: {}".format(title, text))
Bây giờ sau khi chạy tập lệnh trên, chúng ta có thể nhận được các chi tiết khác nhau về tài liệu cụ thể. Lưu ý rằng chúng tôi chỉ có thể áp dụng tập lệnh này trên các tài liệu phiên bản Office 2007 trở lên.
Chương này sẽ giải thích các nguyên tắc cơ bản liên quan đến việc thực hiện pháp y mạng bằng Python.
Hiểu về pháp y mạng
Pháp y mạng là một nhánh của pháp y kỹ thuật số đề cập đến việc giám sát và phân tích lưu lượng mạng máy tính, cả cục bộ và mạng WAN (mạng diện rộng), nhằm mục đích thu thập thông tin, thu thập bằng chứng hoặc phát hiện xâm nhập. Pháp y mạng đóng một vai trò quan trọng trong việc điều tra tội phạm kỹ thuật số như trộm cắp tài sản trí tuệ hoặc rò rỉ thông tin. Hình ảnh về truyền thông mạng giúp điều tra viên giải quyết một số câu hỏi quan trọng như sau:
Những trang web nào đã được truy cập?
Loại nội dung nào đã được tải lên trên mạng của chúng tôi?
Loại nội dung nào đã được tải xuống từ mạng của chúng tôi?
Những máy chủ nào đang được truy cập?
Có ai đó đang gửi thông tin nhạy cảm bên ngoài tường lửa của công ty không?
Công cụ tìm bằng chứng Internet (IEF)
IEF là một công cụ pháp y kỹ thuật số để tìm, phân tích và trình bày bằng chứng kỹ thuật số được tìm thấy trên các phương tiện kỹ thuật số khác nhau như máy tính, điện thoại thông minh, máy tính bảng, v.v. Nó rất phổ biến và được sử dụng bởi hàng nghìn chuyên gia pháp y.
Sử dụng IEF
Do tính phổ biến của nó, IEF được các chuyên gia pháp y sử dụng ở mức độ lớn. Một số công dụng của IEF như sau:
Do khả năng tìm kiếm mạnh mẽ, nó được sử dụng để tìm kiếm đồng thời nhiều tệp hoặc phương tiện dữ liệu.
Nó cũng được sử dụng để khôi phục dữ liệu đã xóa từ không gian chưa được phân bổ của RAM thông qua các kỹ thuật khắc mới.
Nếu các nhà điều tra muốn xây dựng lại các trang web ở định dạng ban đầu của chúng vào ngày chúng được mở, thì họ có thể sử dụng IEF.
Nó cũng được sử dụng để tìm kiếm khối lượng đĩa logic hoặc vật lý.
Bán báo cáo từ IEF sang CSV bằng Python
IEF lưu trữ dữ liệu trong cơ sở dữ liệu SQLite và sau tập lệnh Python sẽ tự động xác định các bảng kết quả trong cơ sở dữ liệu IEF và kết xuất chúng vào các tệp CSV tương ứng.
Quá trình này được thực hiện theo các bước hiển thị bên dưới
Đầu tiên, tạo cơ sở dữ liệu kết quả IEF sẽ là một tệp cơ sở dữ liệu SQLite kết thúc bằng phần mở rộng .db.
Sau đó, truy vấn cơ sở dữ liệu đó để xác định tất cả các bảng.
Cuối cùng, ghi bảng kết quả này vào một tệp CSV riêng lẻ.
Mã Python
Hãy để chúng tôi xem cách sử dụng mã Python cho mục đích này -
Đối với tập lệnh Python, hãy nhập các thư viện cần thiết như sau:
from __future__ import print_function
import argparse
import csv
import os
import sqlite3
import sys
Bây giờ, chúng ta cần cung cấp đường dẫn đến tệp cơ sở dữ liệu IEF -
if __name__ == '__main__':
parser = argparse.ArgumentParser('IEF to CSV')
parser.add_argument("IEF_DATABASE", help="Input IEF database")
parser.add_argument("OUTPUT_DIR", help="Output DIR")
args = parser.parse_args()
Bây giờ, chúng tôi sẽ xác nhận sự tồn tại của cơ sở dữ liệu IEF như sau:
if not os.path.exists(args.OUTPUT_DIR):
os.makedirs(args.OUTPUT_DIR)
if os.path.exists(args.IEF_DATABASE) and \ os.path.isfile(args.IEF_DATABASE):
main(args.IEF_DATABASE, args.OUTPUT_DIR)
else:
print("[-] Supplied input file {} does not exist or is not a " "file".format(args.IEF_DATABASE))
sys.exit(1)
Bây giờ, như chúng ta đã làm trong các tập lệnh trước đó, hãy tạo kết nối với cơ sở dữ liệu SQLite như sau để thực thi các truy vấn thông qua con trỏ:
def main(database, out_directory):
print("[+] Connecting to SQLite database")
conn = sqlite3.connect(database)
c = conn.cursor()
Các dòng mã sau sẽ lấy tên của các bảng từ cơ sở dữ liệu:
print("List of all tables to extract")
c.execute("select * from sqlite_master where type = 'table'")
tables = [x[2] for x in c.fetchall() if not x[2].startswith('_') and not x[2].endswith('_DATA')]
Bây giờ, chúng tôi sẽ chọn tất cả dữ liệu từ bảng và bằng cách sử dụng fetchall() trên đối tượng con trỏ, chúng tôi sẽ lưu trữ danh sách các bộ giá trị chứa toàn bộ dữ liệu của bảng trong một biến -
print("Dumping {} tables to CSV files in {}".format(len(tables), out_directory))
for table in tables:
c.execute("pragma table_info('{}')".format(table))
table_columns = [x[1] for x in c.fetchall()]
c.execute("select * from '{}'".format(table))
table_data = c.fetchall()
Bây giờ, bằng cách sử dụng CSV_Writer() chúng tôi sẽ viết nội dung trong tệp CSV -
csv_name = table + '.csv'
csv_path = os.path.join(out_directory, csv_name)
print('[+] Writing {} table to {} CSV file'.format(table,csv_name))
with open(csv_path, "w", newline = "") as csvfile:
csv_writer = csv.writer(csvfile)
csv_writer.writerow(table_columns)
csv_writer.writerows(table_data)
Tập lệnh trên sẽ tìm nạp tất cả dữ liệu từ các bảng của cơ sở dữ liệu IEF và ghi nội dung vào tệp CSV mà chúng tôi chọn.
Làm việc với dữ liệu được lưu trong bộ nhớ đệm
Từ cơ sở dữ liệu kết quả của IEF, chúng tôi có thể tìm nạp thêm thông tin không nhất thiết phải được hỗ trợ bởi chính IEF. Chúng tôi có thể tìm nạp dữ liệu đã lưu trong bộ nhớ cache, một sản phẩm bi để biết thông tin, từ nhà cung cấp dịch vụ email như Yahoo, Google, v.v. bằng cách sử dụng cơ sở dữ liệu kết quả IEF.
Sau đây là tập lệnh Python để truy cập thông tin dữ liệu được lưu trong bộ nhớ cache từ Yahoo mail, được truy cập trên Google Chrome, bằng cách sử dụng cơ sở dữ liệu IEF. Lưu ý rằng các bước sẽ giống hoặc ít hơn như sau trong tập lệnh Python cuối cùng.
Đầu tiên, nhập các thư viện cần thiết cho Python như sau:
from __future__ import print_function
import argparse
import csv
import os
import sqlite3
import sys
import json
Bây giờ, cung cấp đường dẫn đến tệp cơ sở dữ liệu IEF cùng với hai đối số vị trí được trình xử lý dòng lệnh chấp nhận như được thực hiện trong tập lệnh cuối cùng -
if __name__ == '__main__':
parser = argparse.ArgumentParser('IEF to CSV')
parser.add_argument("IEF_DATABASE", help="Input IEF database")
parser.add_argument("OUTPUT_DIR", help="Output DIR")
args = parser.parse_args()
Bây giờ, xác nhận sự tồn tại của cơ sở dữ liệu IEF như sau:
directory = os.path.dirname(args.OUTPUT_CSV)
if not os.path.exists(directory):os.makedirs(directory)
if os.path.exists(args.IEF_DATABASE) and \ os.path.isfile(args.IEF_DATABASE):
main(args.IEF_DATABASE, args.OUTPUT_CSV)
else: print("Supplied input file {} does not exist or is not a " "file".format(args.IEF_DATABASE))
sys.exit(1)
Bây giờ, tạo kết nối với cơ sở dữ liệu SQLite như sau để thực thi các truy vấn thông qua con trỏ -
def main(database, out_csv):
print("[+] Connecting to SQLite database")
conn = sqlite3.connect(database)
c = conn.cursor()
Bạn có thể sử dụng các dòng mã sau để tìm nạp các phiên bản của bản ghi bộ nhớ cache liên hệ Yahoo Mail -
print("Querying IEF database for Yahoo Contact Fragments from " "the Chrome Cache Records Table")
try:
c.execute("select * from 'Chrome Cache Records' where URL like " "'https://data.mail.yahoo.com" "/classicab/v2/contacts/?format=json%'")
except sqlite3.OperationalError:
print("Received an error querying the database -- database may be" "corrupt or not have a Chrome Cache Records table")
sys.exit(2)
Bây giờ, danh sách các bộ giá trị được trả về từ truy vấn trên sẽ được lưu vào một biến như sau:
contact_cache = c.fetchall()
contact_data = process_contacts(contact_cache)
write_csv(contact_data, out_csv)
Lưu ý rằng ở đây chúng tôi sẽ sử dụng hai phương pháp cụ thể là process_contacts() để thiết lập danh sách kết quả cũng như lặp lại qua từng bản ghi bộ nhớ đệm liên hệ và json.loads() để lưu trữ dữ liệu JSON được trích xuất từ bảng thành một biến để thao tác thêm -
def process_contacts(contact_cache):
print("[+] Processing {} cache files matching Yahoo contact cache " " data".format(len(contact_cache)))
results = []
for contact in contact_cache:
url = contact[0]
first_visit = contact[1]
last_visit = contact[2]
last_sync = contact[3]
loc = contact[8]
contact_json = json.loads(contact[7].decode())
total_contacts = contact_json["total"]
total_count = contact_json["count"]
if "contacts" not in contact_json:
continue
for c in contact_json["contacts"]:
name, anni, bday, emails, phones, links = ("", "", "", "", "", "")
if "name" in c:
name = c["name"]["givenName"] + " " + \ c["name"]["middleName"] + " " + c["name"]["familyName"]
if "anniversary" in c:
anni = c["anniversary"]["month"] + \"/" + c["anniversary"]["day"] + "/" + \c["anniversary"]["year"]
if "birthday" in c:
bday = c["birthday"]["month"] + "/" + \c["birthday"]["day"] + "/" + c["birthday"]["year"]
if "emails" in c:
emails = ', '.join([x["ep"] for x in c["emails"]])
if "phones" in c:
phones = ', '.join([x["ep"] for x in c["phones"]])
if "links" in c:
links = ', '.join([x["ep"] for x in c["links"]])
Bây giờ đối với công ty, tiêu đề và ghi chú, phương thức get được sử dụng như hình dưới đây:
company = c.get("company", "")
title = c.get("jobTitle", "")
notes = c.get("notes", "")
Bây giờ, chúng ta hãy nối danh sách siêu dữ liệu và các phần tử dữ liệu được trích xuất vào danh sách kết quả như sau:
results.append([url, first_visit, last_visit, last_sync, loc, name, bday,anni, emails, phones, links, company, title, notes,total_contacts, total_count])
return results
Bây giờ, bằng cách sử dụng CSV_Writer() , chúng tôi sẽ viết nội dung trong tệp CSV -
def write_csv(data, output):
print("[+] Writing {} contacts to {}".format(len(data), output))
with open(output, "w", newline="") as csvfile:
csv_writer = csv.writer(csvfile)
csv_writer.writerow([
"URL", "First Visit (UTC)", "Last Visit (UTC)",
"Last Sync (UTC)", "Location", "Contact Name", "Bday",
"Anniversary", "Emails", "Phones", "Links", "Company", "Title",
"Notes", "Total Contacts", "Count of Contacts in Cache"])
csv_writer.writerows(data)
Với sự trợ giúp của script trên, chúng ta có thể xử lý dữ liệu đã lưu trong bộ đệm từ Yahoo mail bằng cách sử dụng cơ sở dữ liệu IEF.
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ó 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 việc 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 việc 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 điề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, 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ể 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ố bởi 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ư hình dưới đây
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.
Các chương trước đã thảo luận về tầm quan trọng và quy trình của pháp y mạng và các khái niệm liên quan. Trong chương này, chúng ta hãy tìm hiểu về vai trò của email trong pháp y kỹ thuật số và việc điều tra chúng bằng Python.
Vai trò của Email trong Điều tra
Email đóng một vai trò rất quan trọng trong giao tiếp kinh doanh và đã nổi lên như một trong những ứng dụng quan trọng nhất trên internet. Chúng là một chế độ thuận tiện để gửi tin nhắn cũng như tài liệu, không chỉ từ máy tính mà còn từ các thiết bị điện tử khác như điện thoại di động và máy tính bảng.
Mặt tiêu cực của email là bọn tội phạm có thể làm rò rỉ thông tin quan trọng về công ty của họ. Do đó, vai trò của email trong pháp y kỹ thuật số đã được gia tăng trong những năm gần đây. Trong pháp y kỹ thuật số, email được coi là bằng chứng quan trọng và Phân tích tiêu đề email đã trở nên quan trọng để thu thập bằng chứng trong quá trình pháp y.
Điều tra viên có các mục tiêu sau khi thực hiện pháp y qua email:
- Để xác định tội phạm chính
- Thu thập bằng chứng cần thiết
- Trình bày những phát hiện
- Để xây dựng trường hợp
Những thách thức trong pháp y qua email
Pháp y qua email đóng một vai trò rất quan trọng trong việc điều tra vì hầu hết các giao tiếp trong thời đại hiện nay đều dựa vào email. Tuy nhiên, một nhà điều tra pháp y qua email có thể gặp những thách thức sau trong quá trình điều tra -
Email giả mạo
Thách thức lớn nhất trong pháp y email là việc sử dụng các e-mail giả được tạo ra bằng cách thao túng và viết kịch bản tiêu đề, v.v. Trong thể loại này, bọn tội phạm cũng sử dụng email tạm thời, một dịch vụ cho phép người dùng đã đăng ký nhận email tại một địa chỉ tạm thời hết hạn. sau một khoảng thời gian nhất định.
Giả mạo
Một thách thức khác trong pháp y email là giả mạo trong đó tội phạm sử dụng để trình bày email là của người khác. Trong trường hợp này, máy sẽ nhận được cả địa chỉ IP giả cũng như địa chỉ IP gốc.
Gửi lại email ẩn danh
Tại đây, máy chủ Email loại bỏ thông tin nhận dạng từ email trước khi chuyển tiếp nó. Điều này dẫn đến một thách thức lớn khác cho việc điều tra email.
Các kỹ thuật được sử dụng trong điều tra pháp y qua email
Pháp y email là nghiên cứu về nguồn và nội dung của email để làm bằng chứng xác định người gửi và người nhận thực tế của một thư cùng với một số thông tin khác như ngày / giờ truyền và ý định của người gửi. Nó liên quan đến việc điều tra siêu dữ liệu, quét cổng cũng như tìm kiếm từ khóa.
Một số kỹ thuật phổ biến có thể được sử dụng để điều tra pháp y qua email là
- Phân tích tiêu đề
- Điều tra máy chủ
- Điều tra thiết bị mạng
- Dấu vân tay của Người gửi thư
- Số nhận dạng được nhúng phần mềm
Trong các phần sau, chúng ta sẽ tìm hiểu cách lấy thông tin bằng Python cho mục đích điều tra email.
Trích xuất thông tin từ tệp EML
Các tệp EML về cơ bản là các email ở định dạng tệp được sử dụng rộng rãi để lưu trữ các email. Chúng là các tệp văn bản có cấu trúc tương thích với nhiều ứng dụng email như Microsoft Outlook, Outlook Express và Windows Live Mail.
Tệp EML lưu trữ tiêu đề email, nội dung nội dung, dữ liệu đính kèm dưới dạng văn bản thuần túy. Nó sử dụng base64 để mã hóa dữ liệu nhị phân và mã hóa Quotes-Printable (QP) để lưu trữ thông tin nội dung. Tập lệnh Python có thể được sử dụng để trích xuất thông tin từ tệp EML được đưa ra dưới đây:
Đầu tiên, nhập các thư viện Python sau như được hiển thị bên dưới:
from __future__ import print_function
from argparse import ArgumentParser, FileType
from email import message_from_file
import os
import quopri
import base64
Trong các thư viện trên, quopriđược sử dụng để giải mã các giá trị được mã hóa QP từ các tệp EML. Mọi dữ liệu được mã hóa base64 đều có thể được giải mã với sự trợ giúp củabase64 thư viện.
Tiếp theo, chúng ta hãy cung cấp đối số cho trình xử lý dòng lệnh. Lưu ý rằng ở đây nó sẽ chỉ chấp nhận một đối số là đường dẫn đến tệp EML như hình dưới đây:
if __name__ == '__main__':
parser = ArgumentParser('Extracting information from EML file')
parser.add_argument("EML_FILE",help="Path to EML File", type=FileType('r'))
args = parser.parse_args()
main(args.EML_FILE)
Bây giờ, chúng ta cần xác định main() trong đó chúng ta sẽ sử dụng phương thức có tên message_from_file()từ thư viện email để đọc tệp giống đối tượng. Ở đây, chúng tôi sẽ truy cập tiêu đề, nội dung nội dung, tệp đính kèm và thông tin trọng tải khác bằng cách sử dụng biến kết quả có tênemlfile như được hiển thị trong mã dưới đây -
def main(input_file):
emlfile = message_from_file(input_file)
for key, value in emlfile._headers:
print("{}: {}".format(key, value))
print("\nBody\n")
if emlfile.is_multipart():
for part in emlfile.get_payload():
process_payload(part)
else:
process_payload(emlfile[1])
Bây giờ, chúng ta cần xác định process_payload() trong đó chúng tôi sẽ trích xuất nội dung nội dung thư bằng cách sử dụng get_payload()phương pháp. Chúng tôi sẽ giải mã dữ liệu được mã hóa QP bằng cách sử dụngquopri.decodestring()chức năng. Chúng tôi cũng sẽ kiểm tra loại MIME nội dung để nó có thể xử lý việc lưu trữ email đúng cách. Quan sát đoạn mã dưới đây -
def process_payload(payload):
print(payload.get_content_type() + "\n" + "=" * len(payload.get_content_type()))
body = quopri.decodestring(payload.get_payload())
if payload.get_charset():
body = body.decode(payload.get_charset())
else:
try:
body = body.decode()
except UnicodeDecodeError:
body = body.decode('cp1252')
if payload.get_content_type() == "text/html":
outfile = os.path.basename(args.EML_FILE.name) + ".html"
open(outfile, 'w').write(body)
elif payload.get_content_type().startswith('application'):
outfile = open(payload.get_filename(), 'wb')
body = base64.b64decode(payload.get_payload())
outfile.write(body)
outfile.close()
print("Exported: {}\n".format(outfile.name))
else:
print(body)
Sau khi thực hiện tập lệnh trên, chúng ta sẽ nhận được thông tin tiêu đề cùng với các trọng tải khác nhau trên bảng điều khiển.
Phân tích tệp MSG bằng Python
Thư điện tử có nhiều định dạng khác nhau. MSG là một trong những loại định dạng được Microsoft Outlook và Exchange sử dụng. Các tệp có phần mở rộng MSG có thể chứa văn bản ASCII thuần túy cho tiêu đề và nội dung thư chính cũng như các siêu liên kết và tệp đính kèm.
Trong phần này, chúng ta sẽ tìm hiểu cách trích xuất thông tin từ tệp MSG bằng Outlook API. Lưu ý rằng tập lệnh Python sau sẽ chỉ hoạt động trên Windows. Đối với điều này, chúng tôi cần cài đặt thư viện Python của bên thứ ba có tênpywin32 như sau -
pip install pywin32
Bây giờ, hãy nhập các thư viện sau bằng các lệnh được hiển thị:
from __future__ import print_function
from argparse import ArgumentParser
import os
import win32com.client
import pywintypes
Bây giờ, chúng ta hãy cung cấp một đối số cho trình xử lý dòng lệnh. Ở đây nó sẽ chấp nhận hai đối số, một là đường dẫn đến tệp MSG và đối số khác sẽ là thư mục đầu ra mong muốn như sau:
if __name__ == '__main__':
parser = ArgumentParser(‘Extracting information from MSG file’)
parser.add_argument("MSG_FILE", help="Path to MSG file")
parser.add_argument("OUTPUT_DIR", help="Path to output folder")
args = parser.parse_args()
out_dir = args.OUTPUT_DIR
if not os.path.exists(out_dir):
os.makedirs(out_dir)
main(args.MSG_FILE, args.OUTPUT_DIR)
Bây giờ, chúng ta cần xác định main() chức năng mà chúng ta sẽ gọi win32com thư viện để thiết lập Outlook API hơn nữa cho phép truy cập vào MAPI không gian tên.
def main(msg_file, output_dir):
mapi = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
msg = mapi.OpenSharedItem(os.path.abspath(args.MSG_FILE))
display_msg_attribs(msg)
display_msg_recipients(msg)
extract_msg_body(msg, output_dir)
extract_attachments(msg, output_dir)
Bây giờ, hãy xác định các hàm khác nhau mà chúng ta đang sử dụng trong tập lệnh này. Đoạn mã đưa ra bên dưới cho thấy việc xác địnhdisplay_msg_attribs() chức năng cho phép chúng tôi hiển thị các thuộc tính khác nhau của thư như chủ đề, tới, BCC, CC, Kích thước, Tên người gửi, đã gửi, v.v.
def display_msg_attribs(msg):
attribs = [
'Application', 'AutoForwarded', 'BCC', 'CC', 'Class',
'ConversationID', 'ConversationTopic', 'CreationTime',
'ExpiryTime', 'Importance', 'InternetCodePage', 'IsMarkedAsTask',
'LastModificationTime', 'Links','ReceivedTime', 'ReminderSet',
'ReminderTime', 'ReplyRecipientNames', 'Saved', 'Sender',
'SenderEmailAddress', 'SenderEmailType', 'SenderName', 'Sent',
'SentOn', 'SentOnBehalfOfName', 'Size', 'Subject',
'TaskCompletedDate', 'TaskDueDate', 'To', 'UnRead'
]
print("\nMessage Attributes")
for entry in attribs:
print("{}: {}".format(entry, getattr(msg, entry, 'N/A')))
Bây giờ, xác định display_msg_recipeints() chức năng lặp qua các tin nhắn và hiển thị chi tiết người nhận.
def display_msg_recipients(msg):
recipient_attrib = ['Address', 'AutoResponse', 'Name', 'Resolved', 'Sendable']
i = 1
while True:
try:
recipient = msg.Recipients(i)
except pywintypes.com_error:
break
print("\nRecipient {}".format(i))
print("=" * 15)
for entry in recipient_attrib:
print("{}: {}".format(entry, getattr(recipient, entry, 'N/A')))
i += 1
Tiếp theo, chúng tôi xác định extract_msg_body() chức năng trích xuất nội dung nội dung, HTML cũng như Văn bản thuần túy, từ thư.
def extract_msg_body(msg, out_dir):
html_data = msg.HTMLBody.encode('cp1252')
outfile = os.path.join(out_dir, os.path.basename(args.MSG_FILE))
open(outfile + ".body.html", 'wb').write(html_data)
print("Exported: {}".format(outfile + ".body.html"))
body_data = msg.Body.encode('cp1252')
open(outfile + ".body.txt", 'wb').write(body_data)
print("Exported: {}".format(outfile + ".body.txt"))
Tiếp theo, chúng ta sẽ xác định extract_attachments() hàm xuất dữ liệu đính kèm vào thư mục đầu ra mong muốn.
def extract_attachments(msg, out_dir):
attachment_attribs = ['DisplayName', 'FileName', 'PathName', 'Position', 'Size']
i = 1 # Attachments start at 1
while True:
try:
attachment = msg.Attachments(i)
except pywintypes.com_error:
break
Khi tất cả các chức năng được xác định, chúng tôi sẽ in tất cả các thuộc tính vào bảng điều khiển với dòng mã sau:
print("\nAttachment {}".format(i))
print("=" * 15)
for entry in attachment_attribs:
print('{}: {}'.format(entry, getattr(attachment, entry,"N/A")))
outfile = os.path.join(os.path.abspath(out_dir),os.path.split(args.MSG_FILE)[-1])
if not os.path.exists(outfile):
os.makedirs(outfile)
outfile = os.path.join(outfile, attachment.FileName)
attachment.SaveAsFile(outfile)
print("Exported: {}".format(outfile))
i += 1
Sau khi chạy tập lệnh trên, chúng ta sẽ nhận được các thuộc tính của tin nhắn và các tệp đính kèm của nó trong cửa sổ bảng điều khiển cùng với một số tệp trong thư mục đầu ra.
Cấu trúc tệp MBOX từ Google Takeout bằng Python
Tệp MBOX là tệp văn bản có định dạng đặc biệt chia nhỏ các thư được lưu trữ bên trong. Chúng thường được tìm thấy cùng với hệ thống UNIX, Thunderbolt và Google Takeouts.
Trong phần này, bạn sẽ thấy một tập lệnh Python, nơi chúng ta sẽ cấu trúc các tệp MBOX lấy từ Google Takeouts. Nhưng trước đó chúng ta phải biết rằng làm thế nào chúng ta có thể tạo các tệp MBOX này bằng cách sử dụng tài khoản Google hoặc tài khoản Gmail của chúng tôi.
Nhận Hộp thư Tài khoản Google ở Định dạng MBX
Có được hộp thư tài khoản Google đồng nghĩa với việc sao lưu tài khoản Gmail của chúng ta. Sao lưu có thể được thực hiện vì nhiều lý do cá nhân hoặc nghề nghiệp. Lưu ý rằng Google cung cấp tính năng sao lưu dữ liệu Gmail. Để chuyển hộp thư tài khoản Google của chúng tôi sang định dạng MBOX, bạn cần thực hiện theo các bước dưới đây -
Mở My account bảng điều khiển.
Chuyển đến phần Thông tin cá nhân & quyền riêng tư và chọn Kiểm soát liên kết nội dung của bạn.
Bạn có thể tạo một kho lưu trữ mới hoặc có thể quản lý một kho lưu trữ hiện có. Nếu chúng tôi nhấp vào,CREATE ARCHIVE liên kết, sau đó chúng tôi sẽ nhận được một số hộp kiểm cho từng sản phẩm của Google mà chúng tôi muốn đưa vào.
Sau khi chọn các sản phẩm, chúng tôi sẽ có quyền tự do lựa chọn loại tệp và kích thước tối đa cho kho lưu trữ của chúng tôi cùng với phương thức phân phối để chọn từ danh sách.
Cuối cùng, chúng tôi sẽ nhận được bản sao lưu này ở định dạng MBOX.
Mã Python
Bây giờ, tệp MBOX được thảo luận ở trên có thể được cấu trúc bằng Python như hình dưới đây:
Đầu tiên, cần nhập các thư viện Python như sau:
from __future__ import print_function
from argparse import ArgumentParser
import mailbox
import os
import time
import csv
from tqdm import tqdm
import base64
Tất cả các thư viện đã được sử dụng và giải thích trong các tập lệnh trước đó, ngoại trừ mailbox thư viện được sử dụng để phân tích cú pháp tệp MBOX.
Bây giờ, cung cấp một đối số cho trình xử lý dòng lệnh. Ở đây nó sẽ chấp nhận hai đối số - một là đường dẫn đến tệp MBOX và đối số kia sẽ là thư mục đầu ra mong muốn.
if __name__ == '__main__':
parser = ArgumentParser('Parsing MBOX files')
parser.add_argument("MBOX", help="Path to mbox file")
parser.add_argument(
"OUTPUT_DIR",help = "Path to output directory to write report ""and exported content")
args = parser.parse_args()
main(args.MBOX, args.OUTPUT_DIR)
Bây giờ, sẽ xác định main() chức năng và cuộc gọi mbox lớp thư viện hộp thư với sự trợ giúp của chúng tôi có thể phân tích cú pháp tệp MBOX bằng cách cung cấp đường dẫn của nó -
def main(mbox_file, output_dir):
print("Reading mbox file")
mbox = mailbox.mbox(mbox_file, factory=custom_reader)
print("{} messages to parse".format(len(mbox)))
Bây giờ, hãy xác định một phương pháp đọc cho mailbox thư viện như sau -
def custom_reader(data_stream):
data = data_stream.read()
try:
content = data.decode("ascii")
except (UnicodeDecodeError, UnicodeEncodeError) as e:
content = data.decode("cp1252", errors="replace")
return mailbox.mboxMessage(content)
Bây giờ, hãy tạo một số biến để xử lý thêm như sau:
parsed_data = []
attachments_dir = os.path.join(output_dir, "attachments")
if not os.path.exists(attachments_dir):
os.makedirs(attachments_dir)
columns = [
"Date", "From", "To", "Subject", "X-Gmail-Labels", "Return-Path", "Received",
"Content-Type", "Message-ID","X-GM-THRID", "num_attachments_exported", "export_path"]
Tiếp theo, sử dụng tqdm để tạo thanh tiến trình và theo dõi quá trình lặp lại như sau:
for message in tqdm(mbox):
msg_data = dict()
header_data = dict(message._headers)
for hdr in columns:
msg_data[hdr] = header_data.get(hdr, "N/A")
Bây giờ, hãy kiểm tra thông báo thời tiết có tải trọng hay không. Nếu nó đang có thì chúng tôi sẽ xác địnhwrite_payload() phương pháp như sau -
if len(message.get_payload()):
export_path = write_payload(message, attachments_dir)
msg_data['num_attachments_exported'] = len(export_path)
msg_data['export_path'] = ", ".join(export_path)
Bây giờ, dữ liệu cần được thêm vào. Sau đó, chúng tôi sẽ gọicreate_report() phương pháp như sau -
parsed_data.append(msg_data)
create_report(
parsed_data, os.path.join(output_dir, "mbox_report.csv"), columns)
def write_payload(msg, out_dir):
pyld = msg.get_payload()
export_path = []
if msg.is_multipart():
for entry in pyld:
export_path += write_payload(entry, out_dir)
else:
content_type = msg.get_content_type()
if "application/" in content_type.lower():
content = base64.b64decode(msg.get_payload())
export_path.append(export_content(msg, out_dir, content))
elif "image/" in content_type.lower():
content = base64.b64decode(msg.get_payload())
export_path.append(export_content(msg, out_dir, content))
elif "video/" in content_type.lower():
content = base64.b64decode(msg.get_payload())
export_path.append(export_content(msg, out_dir, content))
elif "audio/" in content_type.lower():
content = base64.b64decode(msg.get_payload())
export_path.append(export_content(msg, out_dir, content))
elif "text/csv" in content_type.lower():
content = base64.b64decode(msg.get_payload())
export_path.append(export_content(msg, out_dir, content))
elif "info/" in content_type.lower():
export_path.append(export_content(msg, out_dir,
msg.get_payload()))
elif "text/calendar" in content_type.lower():
export_path.append(export_content(msg, out_dir,
msg.get_payload()))
elif "text/rtf" in content_type.lower():
export_path.append(export_content(msg, out_dir,
msg.get_payload()))
else:
if "name=" in msg.get('Content-Disposition', "N/A"):
content = base64.b64decode(msg.get_payload())
export_path.append(export_content(msg, out_dir, content))
elif "name=" in msg.get('Content-Type', "N/A"):
content = base64.b64decode(msg.get_payload())
export_path.append(export_content(msg, out_dir, content))
return export_path
Quan sát rằng các câu lệnh if-else ở trên rất dễ hiểu. Bây giờ, chúng ta cần xác định một phương thức sẽ trích xuất tên tệp từmsg đối tượng như sau -
def export_content(msg, out_dir, content_data):
file_name = get_filename(msg)
file_ext = "FILE"
if "." in file_name: file_ext = file_name.rsplit(".", 1)[-1]
file_name = "{}_{:.4f}.{}".format(file_name.rsplit(".", 1)[0], time.time(), file_ext)
file_name = os.path.join(out_dir, file_name)
Bây giờ, với sự trợ giúp của các dòng mã sau, bạn thực sự có thể xuất tệp -
if isinstance(content_data, str):
open(file_name, 'w').write(content_data)
else:
open(file_name, 'wb').write(content_data)
return file_name
Bây giờ, chúng ta hãy xác định một hàm để trích xuất tên tệp từ message để trình bày chính xác tên của các tệp này như sau:
def get_filename(msg):
if 'name=' in msg.get("Content-Disposition", "N/A"):
fname_data = msg["Content-Disposition"].replace("\r\n", " ")
fname = [x for x in fname_data.split("; ") if 'name=' in x]
file_name = fname[0].split("=", 1)[-1]
elif 'name=' in msg.get("Content-Type", "N/A"):
fname_data = msg["Content-Type"].replace("\r\n", " ")
fname = [x for x in fname_data.split("; ") if 'name=' in x]
file_name = fname[0].split("=", 1)[-1]
else:
file_name = "NO_FILENAME"
fchars = [x for x in file_name if x.isalnum() or x.isspace() or x == "."]
return "".join(fchars)
Bây giờ, chúng ta có thể viết tệp CSV bằng cách xác định create_report() chức năng như sau -
def create_report(output_data, output_file, columns):
with open(output_file, 'w', newline="") as outfile:
csvfile = csv.DictWriter(outfile, columns)
csvfile.writeheader()
csvfile.writerows(output_data)
Sau khi bạn chạy tập lệnh được cung cấp ở trên, chúng tôi sẽ nhận được báo cáo CSV và thư mục chứa đầy tệp đính kèm.
Chương này sẽ giải thích các khái niệm khác nhau liên quan đến pháp y của Microsoft Windows và các hiện vật quan trọng mà điều tra viên có thể thu được từ quá trình điều tra.
Giới thiệu
Tạo tác là các đối tượng hoặc khu vực trong hệ thống máy tính có thông tin quan trọng liên quan đến các hoạt động được thực hiện bởi người sử dụng máy tính. Loại và vị trí của thông tin này phụ thuộc vào hệ điều hành. Trong quá trình phân tích pháp y, những hiện vật này đóng một vai trò rất quan trọng trong việc chấp thuận hoặc không chấp thuận quan sát của điều tra viên.
Tầm quan trọng của Windows Artifacts đối với pháp y
Các tạo tác Windows có ý nghĩa quan trọng do những lý do sau:
Khoảng 90% lưu lượng truy cập trên thế giới đến từ các máy tính sử dụng Windows làm hệ điều hành của chúng. Đó là lý do tại sao đối với các giám định viên pháp y kỹ thuật số, Windows tạo tác là thứ rất cần thiết.
Hệ điều hành Windows lưu trữ các loại bằng chứng khác nhau liên quan đến hoạt động của người dùng trên hệ thống máy tính. Đây là một lý do khác cho thấy tầm quan trọng của các tạo tác Windows đối với pháp y kỹ thuật số.
Nhiều lần điều tra viên xoay vòng cuộc điều tra xung quanh các lĩnh vực cũ và truyền thống như dữ liệu người dùng nhồi nhét. Các tạo tác Windows có thể dẫn dắt cuộc điều tra đến các lĩnh vực phi truyền thống như dữ liệu do hệ thống tạo ra hoặc các tạo tác.
Windows cung cấp rất nhiều hiện vật, rất hữu ích cho các nhà điều tra cũng như cho các công ty và cá nhân thực hiện các cuộc điều tra không chính thức.
Sự gia tăng tội phạm mạng trong những năm gần đây là một lý do khác khiến Windows tạo tác quan trọng.
Phần mềm Windows và Tập lệnh Python của chúng
Trong phần này, chúng ta sẽ thảo luận về một số tạo tác Windows và tập lệnh Python để lấy thông tin từ chúng.
Thùng rác
Nó là một trong những tạo tác Windows quan trọng để điều tra pháp y. Thùng rác của Windows chứa các tệp đã bị xóa bởi người dùng, nhưng hệ thống chưa xóa về mặt vật lý. Ngay cả khi người dùng xóa hoàn toàn tệp khỏi hệ thống, nó vẫn đóng vai trò là nguồn điều tra quan trọng. Điều này là do người kiểm tra có thể trích xuất thông tin có giá trị, như đường dẫn tệp gốc cũng như thời gian nó được gửi đến Thùng rác, từ các tệp đã xóa.
Lưu ý rằng việc lưu trữ bằng chứng Thùng rác phụ thuộc vào phiên bản Windows. Trong tập lệnh Python sau, chúng ta sẽ xử lý Windows 7, nơi nó tạo hai tệp:$R tệp chứa nội dung thực của tệp tái chế và $I tệp chứa tên tệp gốc, đường dẫn, kích thước tệp khi tệp bị xóa.
Đối với tập lệnh Python, chúng ta cần cài đặt các mô-đun của bên thứ ba, cụ thể là pytsk3, pyewf và unicodecsv. Chúng ta có thể sử dụngpipđể cài đặt chúng. Chúng ta có thể làm theo các bước sau để trích xuất thông tin từ Thùng rác -
Đầu tiên, chúng ta cần sử dụng phương pháp đệ quy để quét qua $Recycle.bin thư mục và chọn tất cả các tệp bắt đầu bằng $I.
Tiếp theo, chúng ta sẽ đọc nội dung của các tệp và phân tích cú pháp các cấu trúc siêu dữ liệu có sẵn.
Bây giờ, chúng tôi sẽ tìm kiếm tệp $ R được liên kết.
Cuối cùng, chúng tôi sẽ ghi kết quả vào tệp CSV để xem xét.
Hãy để chúng tôi xem cách sử dụng mã Python cho mục đích này -
Đầu tiên, chúng ta cần nhập các thư viện Python sau:
from __future__ import print_function
from argparse import ArgumentParser
import datetime
import os
import struct
from utility.pytskutil import TSKUtil
import unicodecsv as csv
Tiếp theo, chúng ta cần cung cấp đối số cho trình xử lý dòng lệnh. Lưu ý rằng ở đây nó sẽ chấp nhận ba đối số - đầu tiên là đường dẫn đến tệp bằng chứng, thứ hai là loại tệp bằng chứng và thứ ba là đường dẫn đầu ra mong muốn đến báo cáo CSV, như được hiển thị bên dưới -
if __name__ == '__main__':
parser = argparse.ArgumentParser('Recycle Bin evidences')
parser.add_argument('EVIDENCE_FILE', help = "Path to evidence file")
parser.add_argument('IMAGE_TYPE', help = "Evidence file format",
choices = ('ewf', 'raw'))
parser.add_argument('CSV_REPORT', help = "Path to CSV report")
args = parser.parse_args()
main(args.EVIDENCE_FILE, args.IMAGE_TYPE, args.CSV_REPORT)
Bây giờ, xác định main()chức năng sẽ xử lý tất cả các quá trình. Nó sẽ tìm kiếm$I tập tin như sau -
def main(evidence, image_type, report_file):
tsk_util = TSKUtil(evidence, image_type)
dollar_i_files = tsk_util.recurse_files("$I", path = '/$Recycle.bin',logic = "startswith") if dollar_i_files is not None: processed_files = process_dollar_i(tsk_util, dollar_i_files) write_csv(report_file,['file_path', 'file_size', 'deleted_time','dollar_i_file', 'dollar_r_file', 'is_directory'],processed_files) else: print("No $I files found")
Bây giờ, nếu chúng tôi tìm thấy $I tệp, sau đó nó phải được gửi đến process_dollar_i() chức năng sẽ chấp nhận tsk_util đối tượng cũng như danh sách $I các tệp, như được hiển thị bên dưới -
def process_dollar_i(tsk_util, dollar_i_files):
processed_files = []
for dollar_i in dollar_i_files:
file_attribs = read_dollar_i(dollar_i[2])
if file_attribs is None:
continue
file_attribs['dollar_i_file'] = os.path.join('/$Recycle.bin', dollar_i[1][1:])
Bây giờ, hãy tìm kiếm các tệp $ R như sau:
recycle_file_path = os.path.join('/$Recycle.bin',dollar_i[1].rsplit("/", 1)[0][1:]) dollar_r_files = tsk_util.recurse_files( "$R" + dollar_i[0][2:],path = recycle_file_path, logic = "startswith")
if dollar_r_files is None:
dollar_r_dir = os.path.join(recycle_file_path,"$R" + dollar_i[0][2:])
dollar_r_dirs = tsk_util.query_directory(dollar_r_dir)
if dollar_r_dirs is None:
file_attribs['dollar_r_file'] = "Not Found"
file_attribs['is_directory'] = 'Unknown'
else:
file_attribs['dollar_r_file'] = dollar_r_dir
file_attribs['is_directory'] = True
else:
dollar_r = [os.path.join(recycle_file_path, r[1][1:])for r in dollar_r_files]
file_attribs['dollar_r_file'] = ";".join(dollar_r)
file_attribs['is_directory'] = False
processed_files.append(file_attribs)
return processed_files
Bây giờ, xác định read_dollar_i() phương pháp để đọc $Inói cách khác, phân tích cú pháp siêu dữ liệu. Chúng tôi sẽ sử dụngread_random()để đọc tám byte đầu tiên của chữ ký. Điều này sẽ không trả về nếu chữ ký không khớp. Sau đó, chúng ta sẽ phải đọc và giải nén các giá trị từ$I tệp nếu đó là tệp hợp lệ.
def read_dollar_i(file_obj):
if file_obj.read_random(0, 8) != '\x01\x00\x00\x00\x00\x00\x00\x00':
return None
raw_file_size = struct.unpack('<q', file_obj.read_random(8, 8))
raw_deleted_time = struct.unpack('<q', file_obj.read_random(16, 8))
raw_file_path = file_obj.read_random(24, 520)
Bây giờ, sau khi giải nén các tệp này, chúng ta cần giải thích các số nguyên thành các giá trị mà con người có thể đọc được bằng cách sử dụng sizeof_fmt() chức năng như hình dưới đây -
file_size = sizeof_fmt(raw_file_size[0])
deleted_time = parse_windows_filetime(raw_deleted_time[0])
file_path = raw_file_path.decode("utf16").strip("\x00")
return {'file_size': file_size, 'file_path': file_path,'deleted_time': deleted_time}
Bây giờ, chúng ta cần xác định sizeof_fmt() chức năng như sau -
def sizeof_fmt(num, suffix = 'B'):
for unit in ['', 'Ki', 'Mi', 'Gi', 'Ti', 'Pi', 'Ei', 'Zi']:
if abs(num) < 1024.0:
return "%3.1f%s%s" % (num, unit, suffix)
num /= 1024.0
return "%.1f%s%s" % (num, 'Yi', suffix)
Bây giờ, hãy xác định một hàm cho các số nguyên được diễn giải thành ngày và giờ được định dạng như sau:
def parse_windows_filetime(date_value):
microseconds = float(date_value) / 10
ts = datetime.datetime(1601, 1, 1) + datetime.timedelta(
microseconds = microseconds)
return ts.strftime('%Y-%m-%d %H:%M:%S.%f')
Bây giờ, chúng ta sẽ xác định write_csv() để ghi kết quả đã xử lý vào tệp CSV như sau:
def write_csv(outfile, fieldnames, data):
with open(outfile, 'wb') as open_outfile:
csvfile = csv.DictWriter(open_outfile, fieldnames)
csvfile.writeheader()
csvfile.writerows(data)
Khi bạn chạy tập lệnh trên, chúng tôi sẽ lấy dữ liệu từ tệp $ I và $ R.
Ghi chú dính
Windows Sticky Notes thay thế thói quen viết bằng bút và giấy trong thế giới thực. Những ghi chú này được sử dụng để nổi trên màn hình nền với các tùy chọn khác nhau về màu sắc, phông chữ, v.v. Trong Windows 7, tệp Sticky Notes được lưu trữ dưới dạng tệp OLE do đó trong tập lệnh Python sau, chúng tôi sẽ điều tra tệp OLE này để trích xuất siêu dữ liệu từ Sticky Notes.
Đối với tập lệnh Python này, chúng tôi cần cài đặt các mô-đun của bên thứ ba, cụ thể là olefile, pytsk3, pyewfvà unicodecsv. Chúng ta có thể sử dụng lệnhpip để cài đặt chúng.
Chúng ta có thể làm theo các bước được thảo luận bên dưới để trích xuất thông tin từ tệp Sticky note cụ thể là StickyNote.sn -
Đầu tiên, mở tệp bằng chứng và tìm tất cả các tệp StickyNote.snt.
Sau đó, phân tích cú pháp siêu dữ liệu và nội dung từ luồng OLE và ghi nội dung RTF vào tệp.
Cuối cùng, tạo báo cáo CSV của siêu dữ liệu này.
Mã Python
Hãy để chúng tôi xem cách sử dụng mã Python cho mục đích này -
Đầu tiên, nhập các thư viện Python sau:
from __future__ import print_function
from argparse import ArgumentParser
import unicodecsv as csv
import os
import StringIO
from utility.pytskutil import TSKUtil
import olefile
Tiếp theo, xác định một biến toàn cục sẽ được sử dụng trên tập lệnh này -
REPORT_COLS = ['note_id', 'created', 'modified', 'note_text', 'note_file']
Tiếp theo, chúng ta cần cung cấp đối số cho trình xử lý dòng lệnh. Lưu ý rằng ở đây nó sẽ chấp nhận ba đối số - đầu tiên là đường dẫn đến tệp bằng chứng, thứ hai là loại tệp bằng chứng và thứ ba là đường dẫn đầu ra mong muốn như sau:
if __name__ == '__main__':
parser = argparse.ArgumentParser('Evidence from Sticky Notes')
parser.add_argument('EVIDENCE_FILE', help="Path to evidence file")
parser.add_argument('IMAGE_TYPE', help="Evidence file format",choices=('ewf', 'raw'))
parser.add_argument('REPORT_FOLDER', help="Path to report folder")
args = parser.parse_args()
main(args.EVIDENCE_FILE, args.IMAGE_TYPE, args.REPORT_FOLDER)
Bây giờ, chúng ta sẽ xác định main() chức năng sẽ tương tự như tập lệnh trước đó như được hiển thị bên dưới:
def main(evidence, image_type, report_folder):
tsk_util = TSKUtil(evidence, image_type)
note_files = tsk_util.recurse_files('StickyNotes.snt', '/Users','equals')
Bây giờ, chúng ta hãy lặp lại các tệp kết quả. Sau đó, chúng tôi sẽ gọiparse_snt_file() để xử lý tệp và sau đó chúng tôi sẽ ghi tệp RTF với write_note_rtf() phương pháp như sau -
report_details = []
for note_file in note_files:
user_dir = note_file[1].split("/")[1]
file_like_obj = create_file_like_obj(note_file[2])
note_data = parse_snt_file(file_like_obj)
if note_data is None:
continue
write_note_rtf(note_data, os.path.join(report_folder, user_dir))
report_details += prep_note_report(note_data, REPORT_COLS,"/Users" + note_file[1])
write_csv(os.path.join(report_folder, 'sticky_notes.csv'), REPORT_COLS,report_details)
Tiếp theo, chúng ta cần xác định các hàm khác nhau được sử dụng trong script này.
Trước hết chúng ta sẽ xác định create_file_like_obj() chức năng để đọc kích thước của tệp bằng cách lấy pytskđối tượng tệp. Sau đó, chúng tôi sẽ xác địnhparse_snt_file() hàm sẽ chấp nhận đối tượng giống tệp làm đầu vào của nó và được sử dụng để đọc và diễn giải tệp ghi chú dính.
def parse_snt_file(snt_file):
if not olefile.isOleFile(snt_file):
print("This is not an OLE file")
return None
ole = olefile.OleFileIO(snt_file)
note = {}
for stream in ole.listdir():
if stream[0].count("-") == 3:
if stream[0] not in note:
note[stream[0]] = {"created": ole.getctime(stream[0]),"modified": ole.getmtime(stream[0])}
content = None
if stream[1] == '0':
content = ole.openstream(stream).read()
elif stream[1] == '3':
content = ole.openstream(stream).read().decode("utf-16")
if content:
note[stream[0]][stream[1]] = content
return note
Bây giờ, hãy tạo tệp RTF bằng cách xác định write_note_rtf() chức năng như sau
def write_note_rtf(note_data, report_folder):
if not os.path.exists(report_folder):
os.makedirs(report_folder)
for note_id, stream_data in note_data.items():
fname = os.path.join(report_folder, note_id + ".rtf")
with open(fname, 'w') as open_file:
open_file.write(stream_data['0'])
Bây giờ, chúng tôi sẽ dịch từ điển lồng nhau thành một danh sách phẳng các từ điển thích hợp hơn cho bảng tính CSV. Nó sẽ được thực hiện bằng cách xác địnhprep_note_report()chức năng. Cuối cùng, chúng tôi sẽ xác địnhwrite_csv() chức năng.
def prep_note_report(note_data, report_cols, note_file):
report_details = []
for note_id, stream_data in note_data.items():
report_details.append({
"note_id": note_id,
"created": stream_data['created'],
"modified": stream_data['modified'],
"note_text": stream_data['3'].strip("\x00"),
"note_file": note_file
})
return report_details
def write_csv(outfile, fieldnames, data):
with open(outfile, 'wb') as open_outfile:
csvfile = csv.DictWriter(open_outfile, fieldnames)
csvfile.writeheader()
csvfile.writerows(data)
Sau khi chạy tập lệnh trên, chúng ta sẽ nhận được siêu dữ liệu từ tệp Sticky Notes.
Tệp đăng ký
Các tệp đăng ký Windows chứa nhiều chi tiết quan trọng giống như một kho tàng thông tin cho một nhà phân tích pháp y. Nó là một cơ sở dữ liệu phân cấp có chứa các chi tiết liên quan đến cấu hình hệ điều hành, hoạt động của người dùng, cài đặt phần mềm, v.v. Trong tập lệnh Python sau, chúng ta sẽ truy cập thông tin cơ sở chung từSYSTEM và SOFTWARE nổi mề đay.
Đối với tập lệnh Python này, chúng tôi cần cài đặt các mô-đun của bên thứ ba, cụ thể là pytsk3, pyewf và registry. Chúng ta có thể sử dụngpip để cài đặt chúng.
Chúng tôi có thể làm theo các bước được cung cấp bên dưới để trích xuất thông tin từ sổ đăng ký Windows -
Đầu tiên, tìm tổ hợp đăng ký để xử lý theo tên của nó cũng như theo đường dẫn.
Sau đó, chúng tôi mở các tệp này bằng cách sử dụng mô-đun StringIO và Registry.
Cuối cùng, chúng ta cần xử lý từng hive và in các giá trị đã được phân tích cú pháp vào bảng điều khiển để diễn giải.
Mã Python
Hãy để chúng tôi xem cách sử dụng mã Python cho mục đích này -
Đầu tiên, nhập các thư viện Python sau:
from __future__ import print_function
from argparse import ArgumentParser
import datetime
import StringIO
import struct
from utility.pytskutil import TSKUtil
from Registry import Registry
Bây giờ, cung cấp đối số cho trình xử lý dòng lệnh. Ở đây nó sẽ chấp nhận hai đối số - thứ nhất là đường dẫn đến tệp bằng chứng, thứ hai là loại tệp bằng chứng, như hình dưới đây -
if __name__ == '__main__':
parser = argparse.ArgumentParser('Evidence from Windows Registry')
parser.add_argument('EVIDENCE_FILE', help = "Path to evidence file")
parser.add_argument('IMAGE_TYPE', help = "Evidence file format",
choices = ('ewf', 'raw'))
args = parser.parse_args()
main(args.EVIDENCE_FILE, args.IMAGE_TYPE)
Bây giờ chúng ta sẽ xác định main() chức năng tìm kiếm SYSTEM và SOFTWARE tổ ong trong /Windows/System32/config thư mục như sau -
def main(evidence, image_type):
tsk_util = TSKUtil(evidence, image_type)
tsk_system_hive = tsk_util.recurse_files('system', '/Windows/system32/config', 'equals')
tsk_software_hive = tsk_util.recurse_files('software', '/Windows/system32/config', 'equals')
system_hive = open_file_as_reg(tsk_system_hive[0][2])
software_hive = open_file_as_reg(tsk_software_hive[0][2])
process_system_hive(system_hive)
process_software_hive(software_hive)
Bây giờ, xác định chức năng để mở tệp đăng ký. Với mục đích này, chúng tôi cần thu thập kích thước tệp từpytsk siêu dữ liệu như sau:
def open_file_as_reg(reg_file):
file_size = reg_file.info.meta.size
file_content = reg_file.read_random(0, file_size)
file_like_obj = StringIO.StringIO(file_content)
return Registry.Registry(file_like_obj)
Bây giờ, với sự trợ giúp của phương pháp sau, chúng tôi có thể xử lý SYSTEM> tổ ong -
def process_system_hive(hive):
root = hive.root()
current_control_set = root.find_key("Select").value("Current").value()
control_set = root.find_key("ControlSet{:03d}".format(current_control_set))
raw_shutdown_time = struct.unpack(
'<Q', control_set.find_key("Control").find_key("Windows").value("ShutdownTime").value())
shutdown_time = parse_windows_filetime(raw_shutdown_time[0])
print("Last Shutdown Time: {}".format(shutdown_time))
time_zone = control_set.find_key("Control").find_key("TimeZoneInformation")
.value("TimeZoneKeyName").value()
print("Machine Time Zone: {}".format(time_zone))
computer_name = control_set.find_key("Control").find_key("ComputerName").find_key("ComputerName")
.value("ComputerName").value()
print("Machine Name: {}".format(computer_name))
last_access = control_set.find_key("Control").find_key("FileSystem")
.value("NtfsDisableLastAccessUpdate").value()
last_access = "Disabled" if last_access == 1 else "enabled"
print("Last Access Updates: {}".format(last_access))
Bây giờ, chúng ta cần xác định một hàm cho các số nguyên được diễn giải thành ngày và giờ được định dạng như sau:
def parse_windows_filetime(date_value):
microseconds = float(date_value) / 10
ts = datetime.datetime(1601, 1, 1) + datetime.timedelta(microseconds = microseconds)
return ts.strftime('%Y-%m-%d %H:%M:%S.%f')
def parse_unix_epoch(date_value):
ts = datetime.datetime.fromtimestamp(date_value)
return ts.strftime('%Y-%m-%d %H:%M:%S.%f')
Bây giờ với sự trợ giúp của phương pháp sau, chúng tôi có thể xử lý SOFTWARE tổ ong -
def process_software_hive(hive):
root = hive.root()
nt_curr_ver = root.find_key("Microsoft").find_key("Windows NT")
.find_key("CurrentVersion")
print("Product name: {}".format(nt_curr_ver.value("ProductName").value()))
print("CSD Version: {}".format(nt_curr_ver.value("CSDVersion").value()))
print("Current Build: {}".format(nt_curr_ver.value("CurrentBuild").value()))
print("Registered Owner: {}".format(nt_curr_ver.value("RegisteredOwner").value()))
print("Registered Org:
{}".format(nt_curr_ver.value("RegisteredOrganization").value()))
raw_install_date = nt_curr_ver.value("InstallDate").value()
install_date = parse_unix_epoch(raw_install_date)
print("Installation Date: {}".format(install_date))
Sau khi chạy tập lệnh trên, chúng ta sẽ nhận được siêu dữ liệu được lưu trữ trong các tệp Windows Registry.
Chương này nói về một số tạo tác quan trọng hơn trong Windows và phương pháp trích xuất của chúng bằng Python.
Hoạt động của Người dùng
Windows có NTUSER.DATtệp để lưu trữ các hoạt động khác nhau của người dùng. Mọi hồ sơ người dùng đều có rất nhiều lượt thíchNTUSER.DAT, nơi lưu trữ thông tin và cấu hình cụ thể liên quan đến người dùng đó. Do đó, nó rất hữu ích cho mục đích điều tra của các nhà phân tích pháp y.
Tập lệnh Python sau sẽ phân tích cú pháp một số khóa của NTUSER.DATđể khám phá các hành động của người dùng trên hệ thống. Trước khi tiếp tục, đối với tập lệnh Python, chúng ta cần cài đặt các mô-đun của bên thứ ba, cụ thể làRegistry, pytsk3, pyewf và Jinja2. Chúng ta có thể sử dụng pip để cài đặt chúng.
Chúng ta có thể làm theo các bước sau để trích xuất thông tin từ NTUSER.DAT tập tin -
Đầu tiên, hãy tìm kiếm tất cả NTUSER.DAT các tệp trong hệ thống.
Sau đó phân tích cú pháp WordWheelQuery, TypePath and RunMRU chìa khóa cho mỗi NTUSER.DAT tập tin.
Cuối cùng, chúng tôi sẽ viết các tạo phẩm này, đã được xử lý, vào một báo cáo HTML bằng cách sử dụng Jinja2 fmodule.
Mã Python
Hãy để chúng tôi xem cách sử dụng mã Python cho mục đích này -
Trước hết, chúng ta cần nhập các mô-đun Python sau:
from __future__ import print_function
from argparse import ArgumentParser
import os
import StringIO
import struct
from utility.pytskutil import TSKUtil
from Registry import Registry
import jinja2
Bây giờ, cung cấp đối số cho trình xử lý dòng lệnh. Ở đây nó sẽ chấp nhận ba đối số - đầu tiên là đường dẫn đến tệp bằng chứng, thứ hai là loại tệp bằng chứng và thứ ba là đường dẫn đầu ra mong muốn đến báo cáo HTML, như được hiển thị bên dưới -
if __name__ == '__main__':
parser = argparse.ArgumentParser('Information from user activities')
parser.add_argument('EVIDENCE_FILE',help = "Path to evidence file")
parser.add_argument('IMAGE_TYPE',help = "Evidence file format",choices = ('ewf', 'raw'))
parser.add_argument('REPORT',help = "Path to report file")
args = parser.parse_args()
main(args.EVIDENCE_FILE, args.IMAGE_TYPE, args.REPORT)
Bây giờ, chúng ta hãy xác định main() chức năng tìm kiếm tất cả NTUSER.DAT các tệp, như được hiển thị -
def main(evidence, image_type, report):
tsk_util = TSKUtil(evidence, image_type)
tsk_ntuser_hives = tsk_util.recurse_files('ntuser.dat','/Users', 'equals')
nt_rec = {
'wordwheel': {'data': [], 'title': 'WordWheel Query'},
'typed_path': {'data': [], 'title': 'Typed Paths'},
'run_mru': {'data': [], 'title': 'Run MRU'}
}
Bây giờ, chúng tôi sẽ cố gắng tìm ra chìa khóa trong NTUSER.DAT và khi bạn tìm thấy nó, hãy xác định các chức năng xử lý của người dùng như được hiển thị bên dưới -
for ntuser in tsk_ntuser_hives:
uname = ntuser[1].split("/")
open_ntuser = open_file_as_reg(ntuser[2])
try:
explorer_key = open_ntuser.root().find_key("Software").find_key("Microsoft")
.find_key("Windows").find_key("CurrentVersion").find_key("Explorer")
except Registry.RegistryKeyNotFoundException:
continue
nt_rec['wordwheel']['data'] += parse_wordwheel(explorer_key, uname)
nt_rec['typed_path']['data'] += parse_typed_paths(explorer_key, uname)
nt_rec['run_mru']['data'] += parse_run_mru(explorer_key, uname)
nt_rec['wordwheel']['headers'] = \ nt_rec['wordwheel']['data'][0].keys()
nt_rec['typed_path']['headers'] = \ nt_rec['typed_path']['data'][0].keys()
nt_rec['run_mru']['headers'] = \ nt_rec['run_mru']['data'][0].keys()
Bây giờ, chuyển đối tượng từ điển và đường dẫn của nó tới write_html() phương pháp như sau -
write_html(report, nt_rec)
Bây giờ, hãy xác định một phương pháp, cần pytsk xử lý tệp và đọc nó vào lớp Registry thông qua StringIO lớp học.
def open_file_as_reg(reg_file):
file_size = reg_file.info.meta.size
file_content = reg_file.read_random(0, file_size)
file_like_obj = StringIO.StringIO(file_content)
return Registry.Registry(file_like_obj)
Bây giờ, chúng ta sẽ xác định hàm sẽ phân tích cú pháp và xử lý WordWheelQuery chìa khóa từ NTUSER.DAT tập tin như sau -
def parse_wordwheel(explorer_key, username):
try:
wwq = explorer_key.find_key("WordWheelQuery")
except Registry.RegistryKeyNotFoundException:
return []
mru_list = wwq.value("MRUListEx").value()
mru_order = []
for i in xrange(0, len(mru_list), 2):
order_val = struct.unpack('h', mru_list[i:i + 2])[0]
if order_val in mru_order and order_val in (0, -1):
break
else:
mru_order.append(order_val)
search_list = []
for count, val in enumerate(mru_order):
ts = "N/A"
if count == 0:
ts = wwq.timestamp()
search_list.append({
'timestamp': ts,
'username': username,
'order': count,
'value_name': str(val),
'search': wwq.value(str(val)).value().decode("UTF-16").strip("\x00")
})
return search_list
Bây giờ, chúng ta sẽ xác định hàm sẽ phân tích cú pháp và xử lý TypedPaths chìa khóa từ NTUSER.DAT tập tin như sau -
def parse_typed_paths(explorer_key, username):
try:
typed_paths = explorer_key.find_key("TypedPaths")
except Registry.RegistryKeyNotFoundException:
return []
typed_path_details = []
for val in typed_paths.values():
typed_path_details.append({
"username": username,
"value_name": val.name(),
"path": val.value()
})
return typed_path_details
Bây giờ, chúng ta sẽ xác định hàm sẽ phân tích cú pháp và xử lý RunMRU chìa khóa từ NTUSER.DAT tập tin như sau -
def parse_run_mru(explorer_key, username):
try:
run_mru = explorer_key.find_key("RunMRU")
except Registry.RegistryKeyNotFoundException:
return []
if len(run_mru.values()) == 0:
return []
mru_list = run_mru.value("MRUList").value()
mru_order = []
for i in mru_list:
mru_order.append(i)
mru_details = []
for count, val in enumerate(mru_order):
ts = "N/A"
if count == 0:
ts = run_mru.timestamp()
mru_details.append({
"username": username,
"timestamp": ts,
"order": count,
"value_name": val,
"run_statement": run_mru.value(val).value()
})
return mru_details
Bây giờ, hàm sau sẽ xử lý việc tạo báo cáo HTML:
def write_html(outfile, data_dict):
cwd = os.path.dirname(os.path.abspath(__file__))
env = jinja2.Environment(loader=jinja2.FileSystemLoader(cwd))
template = env.get_template("user_activity.html")
rendering = template.render(nt_data=data_dict)
with open(outfile, 'w') as open_outfile:
open_outfile.write(rendering)
Cuối cùng, chúng tôi có thể viết tài liệu HTML cho báo cáo. Sau khi chạy đoạn mã trên, chúng ta sẽ lấy thông tin từ tệp NTUSER.DAT ở định dạng tài liệu HTML.
LINK tệp
Tệp lối tắt được tạo khi người dùng hoặc hệ điều hành tạo tệp lối tắt cho tệp thường được sử dụng, nhấp đúp hoặc truy cập từ ổ đĩa hệ thống như bộ nhớ đính kèm. Các loại tệp lối tắt như vậy được gọi là tệp liên kết. Bằng cách truy cập các tệp liên kết này, điều tra viên có thể tìm thấy hoạt động của cửa sổ như thời gian và vị trí từ nơi các tệp này đã được truy cập.
Hãy để chúng tôi thảo luận về tập lệnh Python mà chúng tôi có thể sử dụng để lấy thông tin từ các tệp Windows LINK này.
Đối với tập lệnh Python, hãy cài đặt các mô-đun của bên thứ ba, cụ thể là pylnk, pytsk3, pyewf. Chúng ta có thể làm theo các bước sau để trích xuất thông tin từlnk các tập tin
Đầu tiên, hãy tìm kiếm lnk các tệp trong hệ thống.
Sau đó, trích xuất thông tin từ tệp đó bằng cách lặp lại chúng.
Bây giờ, cuối cùng chúng ta cần thông tin này vào báo cáo CSV.
Mã Python
Hãy để chúng tôi xem cách sử dụng mã Python cho mục đích này -
Đầu tiên, nhập các thư viện Python sau:
from __future__ import print_function
from argparse import ArgumentParser
import csv
import StringIO
from utility.pytskutil import TSKUtil
import pylnk
Bây giờ, cung cấp đối số cho trình xử lý dòng lệnh. Ở đây nó sẽ chấp nhận ba đối số - đầu tiên là đường dẫn đến tệp bằng chứng, thứ hai là loại tệp bằng chứng và thứ ba là đường dẫn đầu ra mong muốn đến báo cáo CSV, như được hiển thị bên dưới -
if __name__ == '__main__':
parser = argparse.ArgumentParser('Parsing LNK files')
parser.add_argument('EVIDENCE_FILE', help = "Path to evidence file")
parser.add_argument('IMAGE_TYPE', help = "Evidence file format",choices = ('ewf', 'raw'))
parser.add_argument('CSV_REPORT', help = "Path to CSV report")
args = parser.parse_args()
main(args.EVIDENCE_FILE, args.IMAGE_TYPE, args.CSV_REPORT)
Bây giờ, hãy giải thích tệp bằng chứng bằng cách tạo một đối tượng TSKUtil và lặp lại qua hệ thống tệp để tìm các tệp kết thúc bằng lnk. Nó có thể được thực hiện bằng cách xác địnhmain() chức năng như sau -
def main(evidence, image_type, report):
tsk_util = TSKUtil(evidence, image_type)
lnk_files = tsk_util.recurse_files("lnk", path="/", logic="endswith")
if lnk_files is None:
print("No lnk files found")
exit(0)
columns = [
'command_line_arguments', 'description', 'drive_serial_number',
'drive_type', 'file_access_time', 'file_attribute_flags',
'file_creation_time', 'file_modification_time', 'file_size',
'environmental_variables_location', 'volume_label',
'machine_identifier', 'local_path', 'network_path',
'relative_path', 'working_directory'
]
Bây giờ với sự trợ giúp của mã sau, chúng tôi sẽ lặp lại lnk bằng cách tạo một hàm như sau:
parsed_lnks = []
for entry in lnk_files:
lnk = open_file_as_lnk(entry[2])
lnk_data = {'lnk_path': entry[1], 'lnk_name': entry[0]}
for col in columns:
lnk_data[col] = getattr(lnk, col, "N/A")
lnk.close()
parsed_lnks.append(lnk_data)
write_csv(report, columns + ['lnk_path', 'lnk_name'], parsed_lnks)
Bây giờ chúng ta cần xác định hai hàm, một hàm sẽ mở pytsk đối tượng tệp và đối tượng khác sẽ được sử dụng để viết báo cáo CSV như được hiển thị bên dưới:
def open_file_as_lnk(lnk_file):
file_size = lnk_file.info.meta.size
file_content = lnk_file.read_random(0, file_size)
file_like_obj = StringIO.StringIO(file_content)
lnk = pylnk.file()
lnk.open_file_object(file_like_obj)
return lnk
def write_csv(outfile, fieldnames, data):
with open(outfile, 'wb') as open_outfile:
csvfile = csv.DictWriter(open_outfile, fieldnames)
csvfile.writeheader()
csvfile.writerows(data)
Sau khi chạy tập lệnh trên, chúng tôi sẽ nhận được thông tin từ lnk các tệp trong báo cáo CSV -
Tìm nạp trước tệp
Bất cứ khi nào một ứng dụng đang chạy lần đầu tiên từ một vị trí cụ thể, Windows sẽ tạo prefetch files. Chúng được sử dụng để tăng tốc quá trình khởi động ứng dụng. Phần mở rộng cho các tệp này là.PF và chúng được lưu trữ trong ”\Root\Windows\Prefetch” thư mục.
Các chuyên gia pháp y kỹ thuật số có thể tiết lộ bằng chứng về việc thực hiện chương trình từ một vị trí xác định cùng với các thông tin chi tiết của người dùng. Các tệp tìm nạp trước là hiện vật hữu ích cho người kiểm tra vì mục nhập của họ vẫn còn ngay cả sau khi chương trình đã bị xóa hoặc không được cài đặt.
Hãy để chúng tôi thảo luận về tập lệnh Python sẽ lấy thông tin từ các tệp tìm nạp trước của Windows như được cung cấp bên dưới:
Đối với tập lệnh Python, hãy cài đặt các mô-đun của bên thứ ba, cụ thể là pylnk, pytsk3 và unicodecsv. Nhớ lại rằng chúng ta đã làm việc với các thư viện này trong các tập lệnh Python mà chúng ta đã thảo luận trong các chương trước.
Chúng tôi phải làm theo các bước dưới đây để trích xuất thông tin từ prefetch tập tin -
Đầu tiên, hãy quét tìm .pf tệp mở rộng hoặc tệp tìm nạp trước.
Bây giờ, hãy thực hiện xác minh chữ ký để loại bỏ các trường hợp dương tính giả.
Tiếp theo, phân tích cú pháp định dạng tệp tìm nạp trước của Windows. Điều này khác với phiên bản Windows. Ví dụ, đối với Windows XP là 17, đối với Windows Vista và Windows 7 là 23, 26 đối với Windows 8.1 và 30 đối với Windows 10.
Cuối cùng, chúng tôi sẽ viết kết quả được phân tích cú pháp trong một tệp CSV.
Mã Python
Hãy để chúng tôi xem cách sử dụng mã Python cho mục đích này -
Đầu tiên, nhập các thư viện Python sau:
from __future__ import print_function
import argparse
from datetime import datetime, timedelta
import os
import pytsk3
import pyewf
import struct
import sys
import unicodecsv as csv
from utility.pytskutil import TSKUtil
Bây giờ, cung cấp một đối số cho trình xử lý dòng lệnh. Ở đây nó sẽ chấp nhận hai lập luận, thứ nhất sẽ là đường dẫn đến tệp bằng chứng và thứ hai sẽ là loại tệp bằng chứng. Nó cũng chấp nhận một đối số tùy chọn để chỉ định đường dẫn để quét các tệp tìm nạp trước -
if __name__ == "__main__":
parser = argparse.ArgumentParser('Parsing Prefetch files')
parser.add_argument("EVIDENCE_FILE", help = "Evidence file path")
parser.add_argument("TYPE", help = "Type of Evidence",choices = ("raw", "ewf"))
parser.add_argument("OUTPUT_CSV", help = "Path to write output csv")
parser.add_argument("-d", help = "Prefetch directory to scan",default = "/WINDOWS/PREFETCH")
args = parser.parse_args()
if os.path.exists(args.EVIDENCE_FILE) and \
os.path.isfile(args.EVIDENCE_FILE):
main(args.EVIDENCE_FILE, args.TYPE, args.OUTPUT_CSV, args.d)
else:
print("[-] Supplied input file {} does not exist or is not a ""file".format(args.EVIDENCE_FILE))
sys.exit(1)
Bây giờ, hãy giải thích tệp bằng chứng bằng cách tạo một đối tượng TSKUtil và lặp lại qua hệ thống tệp để tìm các tệp kết thúc bằng .pf. Nó có thể được thực hiện bằng cách xác địnhmain() chức năng như sau -
def main(evidence, image_type, output_csv, path):
tsk_util = TSKUtil(evidence, image_type)
prefetch_dir = tsk_util.query_directory(path)
prefetch_files = None
if prefetch_dir is not None:
prefetch_files = tsk_util.recurse_files(".pf", path=path, logic="endswith")
if prefetch_files is None:
print("[-] No .pf files found")
sys.exit(2)
print("[+] Identified {} potential prefetch files".format(len(prefetch_files)))
prefetch_data = []
for hit in prefetch_files:
prefetch_file = hit[2]
pf_version = check_signature(prefetch_file)
Bây giờ, hãy xác định một phương thức sẽ thực hiện việc xác nhận chữ ký như hình dưới đây:
def check_signature(prefetch_file):
version, signature = struct.unpack("^<2i", prefetch_file.read_random(0, 8))
if signature == 1094927187:
return version
else:
return None
if pf_version is None:
continue
pf_name = hit[0]
if pf_version == 17:
parsed_data = parse_pf_17(prefetch_file, pf_name)
parsed_data.append(os.path.join(path, hit[1].lstrip("//")))
prefetch_data.append(parsed_data)
Bây giờ, hãy bắt đầu xử lý các tệp tìm nạp trước của Windows. Ở đây chúng tôi đang lấy ví dụ về các tệp tìm nạp trước của Windows XP -
def parse_pf_17(prefetch_file, pf_name):
create = convert_unix(prefetch_file.info.meta.crtime)
modify = convert_unix(prefetch_file.info.meta.mtime)
def convert_unix(ts):
if int(ts) == 0:
return ""
return datetime.utcfromtimestamp(ts)
def convert_filetime(ts):
if int(ts) == 0:
return ""
return datetime(1601, 1, 1) + timedelta(microseconds=ts / 10)
Bây giờ, trích xuất dữ liệu được nhúng trong các tệp được tải trước bằng cách sử dụng cấu trúc như sau:
pf_size, name, vol_info, vol_entries, vol_size, filetime, \
count = struct.unpack("<i60s32x3iq16xi",prefetch_file.read_random(12, 136))
name = name.decode("utf-16", "ignore").strip("/x00").split("/x00")[0]
vol_name_offset, vol_name_length, vol_create, \
vol_serial = struct.unpack("<2iqi",prefetch_file.read_random(vol_info, 20))
vol_serial = hex(vol_serial).lstrip("0x")
vol_serial = vol_serial[:4] + "-" + vol_serial[4:]
vol_name = struct.unpack(
"<{}s".format(2 * vol_name_length),
prefetch_file.read_random(vol_info + vol_name_offset,vol_name_length * 2))[0]
vol_name = vol_name.decode("utf-16", "ignore").strip("/x00").split("/x00")[0]
return [
pf_name, name, pf_size, create,
modify, convert_filetime(filetime), count, vol_name,
convert_filetime(vol_create), vol_serial ]
Như chúng tôi đã cung cấp phiên bản tìm nạp trước cho Windows XP nhưng nếu gặp phải các phiên bản tìm nạp trước cho Windows khác thì sao. Sau đó, nó phải hiển thị một thông báo lỗi như sau:
elif pf_version == 23:
print("[-] Windows Vista / 7 PF file {} -- unsupported".format(pf_name))
continue
elif pf_version == 26:
print("[-] Windows 8 PF file {} -- unsupported".format(pf_name))
continue
elif pf_version == 30:
print("[-] Windows 10 PF file {} -- unsupported".format(pf_name))
continue
else:
print("[-] Signature mismatch - Name: {}\nPath: {}".format(hit[0], hit[1]))
continue
write_output(prefetch_data, output_csv)
Bây giờ, hãy xác định phương pháp ghi kết quả vào báo cáo CSV như sau:
def write_output(data, output_csv):
print("[+] Writing csv report")
with open(output_csv, "wb") as outfile:
writer = csv.writer(outfile)
writer.writerow([
"File Name", "Prefetch Name", "File Size (bytes)",
"File Create Date (UTC)", "File Modify Date (UTC)",
"Prefetch Last Execution Date (UTC)",
"Prefetch Execution Count", "Volume", "Volume Create Date",
"Volume Serial", "File Path" ])
writer.writerows(data)
Sau khi chạy đoạn mã trên, chúng ta sẽ lấy thông tin từ các tệp tìm nạp trước của phiên bản Windows XP vào một bảng tính.
Chương này sẽ giải thích về các hiện vật khác mà điều tra viên có thể thu được trong quá trình phân tích pháp y trên Windows.
Nhật ký sự kiện
Tệp nhật ký sự kiện Windows, như tên –suggests, là các tệp đặc biệt lưu trữ các sự kiện quan trọng như khi người dùng đăng nhập trên máy tính, khi chương trình gặp lỗi, về các thay đổi hệ thống, quyền truy cập RDP, các sự kiện cụ thể của ứng dụng, v.v. Các nhà điều tra mạng luôn quan tâm đến sự kiện thông tin nhật ký vì nó cung cấp nhiều thông tin lịch sử hữu ích về việc truy cập hệ thống. Trong tập lệnh Python sau, chúng ta sẽ xử lý cả định dạng nhật ký sự kiện cũ và hiện tại của Windows.
Đối với tập lệnh Python, chúng ta cần cài đặt các mô-đun của bên thứ ba, cụ thể là pytsk3, pyewf, unicodecsv, pyevt and pyevtx. Chúng ta có thể làm theo các bước dưới đây để trích xuất thông tin từ nhật ký sự kiện -
Đầu tiên, hãy tìm kiếm tất cả các bản ghi sự kiện khớp với đối số đầu vào.
Sau đó, thực hiện xác minh chữ ký tệp.
Bây giờ, xử lý từng bản ghi sự kiện được tìm thấy với thư viện thích hợp.
Cuối cùng, ghi đầu ra vào bảng tính.
Mã Python
Hãy để chúng tôi xem cách sử dụng mã Python cho mục đích này -
Đầu tiên, nhập các thư viện Python sau:
from __future__ import print_function
import argparse
import unicodecsv as csv
import os
import pytsk3
import pyewf
import pyevt
import pyevtx
import sys
from utility.pytskutil import TSKUtil
Bây giờ, cung cấp các đối số cho trình xử lý dòng lệnh. Lưu ý rằng ở đây nó sẽ chấp nhận ba đối số - thứ nhất là đường dẫn đến tệp bằng chứng, thứ hai là loại tệp bằng chứng và thứ ba là tên của nhật ký sự kiện cần xử lý.
if __name__ == "__main__":
parser = argparse.ArgumentParser('Information from Event Logs')
parser.add_argument("EVIDENCE_FILE", help = "Evidence file path")
parser.add_argument("TYPE", help = "Type of Evidence",choices = ("raw", "ewf"))
parser.add_argument(
"LOG_NAME",help = "Event Log Name (SecEvent.Evt, SysEvent.Evt, ""etc.)")
parser.add_argument(
"-d", help = "Event log directory to scan",default = "/WINDOWS/SYSTEM32/WINEVT")
parser.add_argument(
"-f", help = "Enable fuzzy search for either evt or"" evtx extension", action = "store_true")
args = parser.parse_args()
if os.path.exists(args.EVIDENCE_FILE) and \ os.path.isfile(args.EVIDENCE_FILE):
main(args.EVIDENCE_FILE, args.TYPE, args.LOG_NAME, args.d, args.f)
else:
print("[-] Supplied input file {} does not exist or is not a ""file".format(args.EVIDENCE_FILE))
sys.exit(1)
Bây giờ, tương tác với nhật ký sự kiện để truy vấn sự tồn tại của đường dẫn do người dùng cung cấp bằng cách tạo TSKUtilvật. Nó có thể được thực hiện với sự giúp đỡ củamain() phương pháp như sau -
def main(evidence, image_type, log, win_event, fuzzy):
tsk_util = TSKUtil(evidence, image_type)
event_dir = tsk_util.query_directory(win_event)
if event_dir is not None:
if fuzzy is True:
event_log = tsk_util.recurse_files(log, path=win_event)
else:
event_log = tsk_util.recurse_files(log, path=win_event, logic="equal")
if event_log is not None:
event_data = []
for hit in event_log:
event_file = hit[2]
temp_evt = write_file(event_file)
Bây giờ, chúng ta cần thực hiện xác minh chữ ký, sau đó xác định một phương thức sẽ ghi toàn bộ nội dung vào thư mục hiện tại -
def write_file(event_file):
with open(event_file.info.name.name, "w") as outfile:
outfile.write(event_file.read_random(0, event_file.info.meta.size))
return event_file.info.name.name
if pyevt.check_file_signature(temp_evt):
evt_log = pyevt.open(temp_evt)
print("[+] Identified {} records in {}".format(
evt_log.number_of_records, temp_evt))
for i, record in enumerate(evt_log.records):
strings = ""
for s in record.strings:
if s is not None:
strings += s + "\n"
event_data.append([
i, hit[0], record.computer_name,
record.user_security_identifier,
record.creation_time, record.written_time,
record.event_category, record.source_name,
record.event_identifier, record.event_type,
strings, "",
os.path.join(win_event, hit[1].lstrip("//"))
])
elif pyevtx.check_file_signature(temp_evt):
evtx_log = pyevtx.open(temp_evt)
print("[+] Identified {} records in {}".format(
evtx_log.number_of_records, temp_evt))
for i, record in enumerate(evtx_log.records):
strings = ""
for s in record.strings:
if s is not None:
strings += s + "\n"
event_data.append([
i, hit[0], record.computer_name,
record.user_security_identifier, "",
record.written_time, record.event_level,
record.source_name, record.event_identifier,
"", strings, record.xml_string,
os.path.join(win_event, hit[1].lstrip("//"))
])
else:
print("[-] {} not a valid event log. Removing temp" file...".format(temp_evt))
os.remove(temp_evt)
continue
write_output(event_data)
else:
print("[-] {} Event log not found in {} directory".format(log, win_event))
sys.exit(3)
else:
print("[-] Win XP Event Log Directory {} not found".format(win_event))
sys.exit(2
Cuối cùng, xác định một phương thức để ghi đầu ra vào bảng tính như sau:
def write_output(data):
output_name = "parsed_event_logs.csv"
print("[+] Writing {} to current working directory: {}".format(
output_name, os.getcwd()))
with open(output_name, "wb") as outfile:
writer = csv.writer(outfile)
writer.writerow([
"Index", "File name", "Computer Name", "SID",
"Event Create Date", "Event Written Date",
"Event Category/Level", "Event Source", "Event ID",
"Event Type", "Data", "XML Data", "File Path"
])
writer.writerows(data)
Khi bạn chạy thành công tập lệnh trên, chúng ta sẽ nhận được thông tin của các sự kiện đăng nhập vào bảng tính.
Lịch sử Internet
Lịch sử Internet rất hữu ích cho các nhà phân tích pháp y; vì hầu hết các tội phạm mạng chỉ xảy ra qua internet. Hãy để chúng tôi xem cách trích xuất lịch sử internet từ Internet Explorer, khi chúng ta thảo luận về tính năng pháp lý của Windows và Internet Explorer đi kèm với Windows theo mặc định.
Trên Internet Explorer, lịch sử internet được lưu trong index.dattập tin. Hãy để chúng tôi xem xét một tập lệnh Python, tập lệnh này sẽ trích xuất thông tin từindex.dat tập tin.
Chúng tôi có thể làm theo các bước dưới đây để trích xuất thông tin từ index.dat tập tin -
Đầu tiên, hãy tìm kiếm index.dat các tệp trong hệ thống.
Sau đó, trích xuất thông tin từ tệp đó bằng cách lặp lại chúng.
Bây giờ, hãy ghi tất cả thông tin này vào báo cáo CSV.
Mã Python
Hãy để chúng tôi xem cách sử dụng mã Python cho mục đích này -
Đầu tiên, nhập các thư viện Python sau:
from __future__ import print_function
import argparse
from datetime import datetime, timedelta
import os
import pytsk3
import pyewf
import pymsiecf
import sys
import unicodecsv as csv
from utility.pytskutil import TSKUtil
Bây giờ, cung cấp các đối số cho trình xử lý dòng lệnh. Lưu ý rằng ở đây nó sẽ chấp nhận hai lập luận - thứ nhất là đường dẫn đến tệp bằng chứng và thứ hai là loại tệp bằng chứng -
if __name__ == "__main__":
parser = argparse.ArgumentParser('getting information from internet history')
parser.add_argument("EVIDENCE_FILE", help = "Evidence file path")
parser.add_argument("TYPE", help = "Type of Evidence",choices = ("raw", "ewf"))
parser.add_argument("-d", help = "Index.dat directory to scan",default = "/USERS")
args = parser.parse_args()
if os.path.exists(args.EVIDENCE_FILE) and os.path.isfile(args.EVIDENCE_FILE):
main(args.EVIDENCE_FILE, args.TYPE, args.d)
else:
print("[-] Supplied input file {} does not exist or is not a ""file".format(args.EVIDENCE_FILE))
sys.exit(1)
Bây giờ, hãy giải thích tệp bằng chứng bằng cách tạo một đối tượng TSKUtilvà lặp qua hệ thống tệp để tìm tệp index.dat. Nó có thể được thực hiện bằng cách xác địnhmain() chức năng như sau -
def main(evidence, image_type, path):
tsk_util = TSKUtil(evidence, image_type)
index_dir = tsk_util.query_directory(path)
if index_dir is not None:
index_files = tsk_util.recurse_files("index.dat", path = path,logic = "equal")
if index_files is not None:
print("[+] Identified {} potential index.dat files".format(len(index_files)))
index_data = []
for hit in index_files:
index_file = hit[2]
temp_index = write_file(index_file)
Bây giờ, xác định một hàm với sự trợ giúp của chúng ta có thể sao chép thông tin của tệp index.dat vào thư mục làm việc hiện tại và sau này chúng có thể được xử lý bởi một mô-đun bên thứ ba -
def write_file(index_file):
with open(index_file.info.name.name, "w") as outfile:
outfile.write(index_file.read_random(0, index_file.info.meta.size))
return index_file.info.name.name
Bây giờ, hãy sử dụng đoạn mã sau để thực hiện xác thực chữ ký với sự trợ giúp của hàm tích hợp cụ thể là check_file_signature() -
if pymsiecf.check_file_signature(temp_index):
index_dat = pymsiecf.open(temp_index)
print("[+] Identified {} records in {}".format(
index_dat.number_of_items, temp_index))
for i, record in enumerate(index_dat.items):
try:
data = record.data
if data is not None:
data = data.rstrip("\x00")
except AttributeError:
if isinstance(record, pymsiecf.redirected):
index_data.append([
i, temp_index, "", "", "", "", "",record.location, "", "", record.offset,os.path.join(path, hit[1].lstrip("//"))])
elif isinstance(record, pymsiecf.leak):
index_data.append([
i, temp_index, record.filename, "","", "", "", "", "", "", record.offset,os.path.join(path, hit[1].lstrip("//"))])
continue
index_data.append([
i, temp_index, record.filename,
record.type, record.primary_time,
record.secondary_time,
record.last_checked_time, record.location,
record.number_of_hits, data, record.offset,
os.path.join(path, hit[1].lstrip("//"))
])
else:
print("[-] {} not a valid index.dat file. Removing "
"temp file..".format(temp_index))
os.remove("index.dat")
continue
os.remove("index.dat")
write_output(index_data)
else:
print("[-] Index.dat files not found in {} directory".format(path))
sys.exit(3)
else:
print("[-] Directory {} not found".format(win_event))
sys.exit(2)
Bây giờ, hãy xác định một phương thức sẽ in đầu ra trong tệp CSV, như được hiển thị bên dưới:
def write_output(data):
output_name = "Internet_Indexdat_Summary_Report.csv"
print("[+] Writing {} with {} parsed index.dat files to current "
"working directory: {}".format(output_name, len(data),os.getcwd()))
with open(output_name, "wb") as outfile:
writer = csv.writer(outfile)
writer.writerow(["Index", "File Name", "Record Name",
"Record Type", "Primary Date", "Secondary Date",
"Last Checked Date", "Location", "No. of Hits",
"Record Data", "Record Offset", "File Path"])
writer.writerows(data)
Sau khi chạy tập lệnh trên, chúng ta sẽ lấy thông tin từ tệp index.dat trong tệp CSV.
Bản sao Volume Shadow
Bản sao bóng là công nghệ được bao gồm trong Windows để sao lưu các bản sao lưu hoặc ảnh chụp nhanh các tệp máy tính theo cách thủ công hoặc tự động. Nó còn được gọi là dịch vụ chụp nhanh âm lượng hoặc dịch vụ đổ bóng âm lượng (VSS).
Với sự trợ giúp của các tệp VSS này, các chuyên gia pháp y có thể có một số thông tin lịch sử về cách hệ thống đã thay đổi theo thời gian và những tệp nào tồn tại trên máy tính. Công nghệ sao chép bóng tối yêu cầu hệ thống tệp phải là NTFS để tạo và lưu trữ các bản sao bóng.
Trong phần này, chúng ta sẽ xem một tập lệnh Python, giúp truy cập vào bất kỳ khối lượng bản sao bóng nào có trong hình ảnh pháp y.
Đối với tập lệnh Python, chúng ta cần cài đặt các mô-đun của bên thứ ba, cụ thể là pytsk3, pyewf, unicodecsv, pyvshadow và vss. Chúng tôi có thể làm theo các bước dưới đây để trích xuất thông tin từ các tệp VSS
Đầu tiên, truy cập khối lượng ảnh thô và xác định tất cả các phân vùng NTFS.
Sau đó, trích xuất thông tin từ các bản sao bóng đó bằng cách lặp lại chúng.
Bây giờ, cuối cùng chúng ta cần tạo một danh sách tệp dữ liệu trong ảnh chụp nhanh.
Mã Python
Hãy để chúng tôi xem cách sử dụng mã Python cho mục đích này -
Đầu tiên, nhập các thư viện Python sau:
from __future__ import print_function
import argparse
from datetime import datetime, timedelta
import os
import pytsk3
import pyewf
import pyvshadow
import sys
import unicodecsv as csv
from utility import vss
from utility.pytskutil import TSKUtil
from utility import pytskutil
Bây giờ, cung cấp các đối số cho trình xử lý dòng lệnh. Ở đây nó sẽ chấp nhận hai đối số - đầu tiên là đường dẫn đến tệp bằng chứng và thứ hai là tệp đầu ra.
if __name__ == "__main__":
parser = argparse.ArgumentParser('Parsing Shadow Copies')
parser.add_argument("EVIDENCE_FILE", help = "Evidence file path")
parser.add_argument("OUTPUT_CSV", help = "Output CSV with VSS file listing")
args = parser.parse_args()
Bây giờ, xác thực sự tồn tại của đường dẫn tệp đầu vào và cũng tách thư mục khỏi tệp đầu ra.
directory = os.path.dirname(args.OUTPUT_CSV)
if not os.path.exists(directory) and directory != "":
os.makedirs(directory)
if os.path.exists(args.EVIDENCE_FILE) and \ os.path.isfile(args.EVIDENCE_FILE):
main(args.EVIDENCE_FILE, args.OUTPUT_CSV)
else:
print("[-] Supplied input file {} does not exist or is not a "
"file".format(args.EVIDENCE_FILE))
sys.exit(1)
Bây giờ, hãy tương tác với khối lượng của tệp bằng chứng bằng cách tạo TSKUtilvật. Nó có thể được thực hiện với sự giúp đỡ củamain() phương pháp như sau -
def main(evidence, output):
tsk_util = TSKUtil(evidence, "raw")
img_vol = tsk_util.return_vol()
if img_vol is not None:
for part in img_vol:
if tsk_util.detect_ntfs(img_vol, part):
print("Exploring NTFS Partition for VSS")
explore_vss(evidence, part.start * img_vol.info.block_size,output)
else:
print("[-] Must be a physical preservation to be compatible ""with this script")
sys.exit(2)
Bây giờ, hãy xác định một phương pháp để khám phá tệp bóng khối lượng được phân tích cú pháp như sau:
def explore_vss(evidence, part_offset, output):
vss_volume = pyvshadow.volume()
vss_handle = vss.VShadowVolume(evidence, part_offset)
vss_count = vss.GetVssStoreCount(evidence, part_offset)
if vss_count > 0:
vss_volume.open_file_object(vss_handle)
vss_data = []
for x in range(vss_count):
print("Gathering data for VSC {} of {}".format(x, vss_count))
vss_store = vss_volume.get_store(x)
image = vss.VShadowImgInfo(vss_store)
vss_data.append(pytskutil.openVSSFS(image, x))
write_csv(vss_data, output)
Cuối cùng, xác định phương thức ghi kết quả trong bảng tính như sau:
def write_csv(data, output):
if data == []:
print("[-] No output results to write")
sys.exit(3)
print("[+] Writing output to {}".format(output))
if os.path.exists(output):
append = True
with open(output, "ab") as csvfile:
csv_writer = csv.writer(csvfile)
headers = ["VSS", "File", "File Ext", "File Type", "Create Date",
"Modify Date", "Change Date", "Size", "File Path"]
if not append:
csv_writer.writerow(headers)
for result_list in data:
csv_writer.writerows(result_list)
Khi bạn chạy thành công tập lệnh Python này, chúng tôi sẽ nhận được thông tin nằm trong VSS vào một bảng tính.
Cho đến bây giờ, chúng ta đã thấy cách lấy các tạo tác trong Windows bằng Python. Trong chương này, chúng ta hãy tìm hiểu về cách điều tra các tạo tác dựa trên nhật ký bằng Python.
Giới thiệu
Hiện vật dựa trên nhật ký là kho tàng thông tin có thể rất hữu ích cho một chuyên gia pháp y kỹ thuật số. Mặc dù chúng tôi có nhiều phần mềm giám sát khác nhau để thu thập thông tin, nhưng vấn đề chính để phân tích thông tin hữu ích từ chúng là chúng tôi cần nhiều dữ liệu.
Nhiều tạo tác dựa trên nhật ký và điều tra bằng Python
Trong phần này, chúng ta hãy thảo luận về các tạo tác dựa trên nhật ký khác nhau và điều tra của chúng bằng Python -
Dấu thời gian
Dấu thời gian truyền tải dữ liệu và thời gian của hoạt động trong nhật ký. Nó là một trong những yếu tố quan trọng của bất kỳ tệp nhật ký nào. Lưu ý rằng các giá trị dữ liệu và thời gian này có thể có nhiều định dạng khác nhau.
Tập lệnh Python được hiển thị bên dưới sẽ lấy ngày-giờ thô làm đầu vào và cung cấp dấu thời gian được định dạng làm đầu ra của nó.
Đối với tập lệnh này, chúng ta cần làm theo các bước sau:
Đầu tiên, thiết lập các đối số sẽ lấy giá trị dữ liệu thô cùng với nguồn dữ liệu và kiểu dữ liệu.
Bây giờ, hãy cung cấp một lớp để cung cấp giao diện chung cho dữ liệu trên các định dạng ngày tháng khác nhau.
Mã Python
Hãy để chúng tôi xem cách sử dụng mã Python cho mục đích này -
Đầu tiên, nhập các mô-đun Python sau:
from __future__ import print_function
from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter
from datetime import datetime as dt
from datetime import timedelta
Bây giờ như thường lệ, chúng ta cần cung cấp đối số cho trình xử lý dòng lệnh. Ở đây nó sẽ chấp nhận ba đối số, đầu tiên là giá trị ngày sẽ được xử lý, thứ hai sẽ là nguồn của giá trị ngày đó và thứ ba sẽ là loại của nó -
if __name__ == '__main__':
parser = ArgumentParser('Timestamp Log-based artifact')
parser.add_argument("date_value", help="Raw date value to parse")
parser.add_argument(
"source", help = "Source format of date",choices = ParseDate.get_supported_formats())
parser.add_argument(
"type", help = "Data type of input value",choices = ('number', 'hex'), default = 'int')
args = parser.parse_args()
date_parser = ParseDate(args.date_value, args.source, args.type)
date_parser.run()
print(date_parser.timestamp)
Bây giờ, chúng ta cần xác định một lớp sẽ chấp nhận các đối số cho giá trị ngày, nguồn ngày và kiểu giá trị -
class ParseDate(object):
def __init__(self, date_value, source, data_type):
self.date_value = date_value
self.source = source
self.data_type = data_type
self.timestamp = None
Bây giờ chúng ta sẽ định nghĩa một phương thức sẽ hoạt động giống như một bộ điều khiển giống như phương thức main () -
def run(self):
if self.source == 'unix-epoch':
self.parse_unix_epoch()
elif self.source == 'unix-epoch-ms':
self.parse_unix_epoch(True)
elif self.source == 'windows-filetime':
self.parse_windows_filetime()
@classmethod
def get_supported_formats(cls):
return ['unix-epoch', 'unix-epoch-ms', 'windows-filetime']
Bây giờ, chúng ta cần xác định hai phương thức sẽ xử lý thời gian kỷ nguyên Unix và FILETIME tương ứng -
def parse_unix_epoch(self, milliseconds=False):
if self.data_type == 'hex':
conv_value = int(self.date_value)
if milliseconds:
conv_value = conv_value / 1000.0
elif self.data_type == 'number':
conv_value = float(self.date_value)
if milliseconds:
conv_value = conv_value / 1000.0
else:
print("Unsupported data type '{}' provided".format(self.data_type))
sys.exit('1')
ts = dt.fromtimestamp(conv_value)
self.timestamp = ts.strftime('%Y-%m-%d %H:%M:%S.%f')
def parse_windows_filetime(self):
if self.data_type == 'hex':
microseconds = int(self.date_value, 16) / 10.0
elif self.data_type == 'number':
microseconds = float(self.date_value) / 10
else:
print("Unsupported data type '{}' provided".format(self.data_type))
sys.exit('1')
ts = dt(1601, 1, 1) + timedelta(microseconds=microseconds)
self.timestamp = ts.strftime('%Y-%m-%d %H:%M:%S.%f')
Sau khi chạy tập lệnh trên, bằng cách cung cấp dấu thời gian, chúng ta có thể nhận được giá trị được chuyển đổi ở định dạng dễ đọc.
Nhật ký Máy chủ Web
Theo quan điểm của chuyên gia pháp y kỹ thuật số, nhật ký máy chủ web là một tạo tác quan trọng khác vì chúng có thể nhận được số liệu thống kê hữu ích của người dùng cùng với thông tin về người dùng và vị trí địa lý. Sau đây là tập lệnh Python sẽ tạo một bảng tính, sau khi xử lý nhật ký máy chủ web, để dễ dàng phân tích thông tin.
Trước hết, chúng ta cần nhập các mô-đun Python sau:
from __future__ import print_function
from argparse import ArgumentParser, FileType
import re
import shlex
import logging
import sys
import csv
logger = logging.getLogger(__file__)
Bây giờ, chúng ta cần xác định các mẫu sẽ được phân tích cú pháp từ các bản ghi -
iis_log_format = [
("date", re.compile(r"\d{4}-\d{2}-\d{2}")),
("time", re.compile(r"\d\d:\d\d:\d\d")),
("s-ip", re.compile(
r"((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4}")),
("cs-method", re.compile(
r"(GET)|(POST)|(PUT)|(DELETE)|(OPTIONS)|(HEAD)|(CONNECT)")),
("cs-uri-stem", re.compile(r"([A-Za-z0-1/\.-]*)")),
("cs-uri-query", re.compile(r"([A-Za-z0-1/\.-]*)")),
("s-port", re.compile(r"\d*")),
("cs-username", re.compile(r"([A-Za-z0-1/\.-]*)")),
("c-ip", re.compile(
r"((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4}")),
("cs(User-Agent)", re.compile(r".*")),
("sc-status", re.compile(r"\d*")),
("sc-substatus", re.compile(r"\d*")),
("sc-win32-status", re.compile(r"\d*")),
("time-taken", re.compile(r"\d*"))]
Bây giờ, cung cấp một đối số cho trình xử lý dòng lệnh. Ở đây nó sẽ chấp nhận hai đối số, đầu tiên sẽ là nhật ký IIS sẽ được xử lý, thứ hai là đường dẫn tệp CSV mong muốn.
if __name__ == '__main__':
parser = ArgumentParser('Parsing Server Based Logs')
parser.add_argument('iis_log', help = "Path to IIS Log",type = FileType('r'))
parser.add_argument('csv_report', help = "Path to CSV report")
parser.add_argument('-l', help = "Path to processing log",default=__name__ + '.log')
args = parser.parse_args()
logger.setLevel(logging.DEBUG)
msg_fmt = logging.Formatter(
"%(asctime)-15s %(funcName)-10s ""%(levelname)-8s %(message)s")
strhndl = logging.StreamHandler(sys.stdout)
strhndl.setFormatter(fmt = msg_fmt)
fhndl = logging.FileHandler(args.log, mode = 'a')
fhndl.setFormatter(fmt = msg_fmt)
logger.addHandler(strhndl)
logger.addHandler(fhndl)
logger.info("Starting IIS Parsing ")
logger.debug("Supplied arguments: {}".format(", ".join(sys.argv[1:])))
logger.debug("System " + sys.platform)
logger.debug("Version " + sys.version)
main(args.iis_log, args.csv_report, logger)
iologger.info("IIS Parsing Complete")
Bây giờ chúng ta cần xác định phương thức main () sẽ xử lý tập lệnh cho thông tin nhật ký hàng loạt -
def main(iis_log, report_file, logger):
parsed_logs = []
for raw_line in iis_log:
line = raw_line.strip()
log_entry = {}
if line.startswith("#") or len(line) == 0:
continue
if '\"' in line:
line_iter = shlex.shlex(line_iter)
else:
line_iter = line.split(" ")
for count, split_entry in enumerate(line_iter):
col_name, col_pattern = iis_log_format[count]
if col_pattern.match(split_entry):
log_entry[col_name] = split_entry
else:
logger.error("Unknown column pattern discovered. "
"Line preserved in full below")
logger.error("Unparsed Line: {}".format(line))
parsed_logs.append(log_entry)
logger.info("Parsed {} lines".format(len(parsed_logs)))
cols = [x[0] for x in iis_log_format]
logger.info("Creating report file: {}".format(report_file))
write_csv(report_file, cols, parsed_logs)
logger.info("Report created")
Cuối cùng, chúng ta cần xác định một phương thức sẽ ghi đầu ra vào bảng tính -
def write_csv(outfile, fieldnames, data):
with open(outfile, 'w', newline="") as open_outfile:
csvfile = csv.DictWriter(open_outfile, fieldnames)
csvfile.writeheader()
csvfile.writerows(data)
Sau khi chạy tập lệnh trên, chúng tôi sẽ nhận được nhật ký dựa trên máy chủ web trong một bảng tính.
Quét các tệp quan trọng bằng YARA
YARA (Yet Another Recursive Algorithm) là một tiện ích đối sánh mẫu được thiết kế để xác định phần mềm độc hại và phản ứng sự cố. Chúng tôi sẽ sử dụng YARA để quét các tệp. Trong tập lệnh Python sau, chúng tôi sẽ sử dụng YARA.
Chúng ta có thể cài đặt YARA với sự trợ giúp của lệnh sau:
pip install YARA
Chúng tôi có thể làm theo các bước được cung cấp bên dưới để sử dụng các quy tắc YARA để quét tệp -
Đầu tiên, thiết lập và biên dịch các quy tắc YARA
Sau đó, quét một tệp duy nhất và sau đó lặp qua các thư mục để xử lý các tệp riêng lẻ.
Cuối cùng, chúng tôi sẽ xuất kết quả sang CSV.
Mã Python
Hãy để chúng tôi xem cách sử dụng mã Python cho mục đích này -
Đầu tiên, chúng ta cần nhập các mô-đun Python sau:
from __future__ import print_function
from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter
import os
import csv
import yara
Tiếp theo, cung cấp đối số cho trình xử lý dòng lệnh. Lưu ý rằng ở đây nó sẽ chấp nhận hai đối số - đầu tiên là đường dẫn đến các quy tắc YARA, thứ hai là tệp được quét.
if __name__ == '__main__':
parser = ArgumentParser('Scanning files by YARA')
parser.add_argument(
'yara_rules',help = "Path to Yara rule to scan with. May be file or folder path.")
parser.add_argument('path_to_scan',help = "Path to file or folder to scan")
parser.add_argument('--output',help = "Path to output a CSV report of scan results")
args = parser.parse_args()
main(args.yara_rules, args.path_to_scan, args.output)
Bây giờ chúng ta sẽ xác định hàm main () sẽ chấp nhận đường dẫn đến các quy tắc yara và tệp được quét -
def main(yara_rules, path_to_scan, output):
if os.path.isdir(yara_rules):
yrules = yara.compile(yara_rules)
else:
yrules = yara.compile(filepath=yara_rules)
if os.path.isdir(path_to_scan):
match_info = process_directory(yrules, path_to_scan)
else:
match_info = process_file(yrules, path_to_scan)
columns = ['rule_name', 'hit_value', 'hit_offset', 'file_name',
'rule_string', 'rule_tag']
if output is None:
write_stdout(columns, match_info)
else:
write_csv(output, columns, match_info)
Bây giờ, hãy xác định một phương thức sẽ lặp qua thư mục và chuyển kết quả đến một phương thức khác để xử lý thêm -
def process_directory(yrules, folder_path):
match_info = []
for root, _, files in os.walk(folder_path):
for entry in files:
file_entry = os.path.join(root, entry)
match_info += process_file(yrules, file_entry)
return match_info
Tiếp theo, xác định hai chức năng. Lưu ý rằng trước tiên chúng ta sẽ sử dụngmatch() phương pháp để yrulesđối tượng và đối tượng khác sẽ báo cáo thông tin khớp đó với bảng điều khiển nếu người dùng không chỉ định bất kỳ tệp đầu ra nào. Quan sát mã hiển thị bên dưới -
def process_file(yrules, file_path):
match = yrules.match(file_path)
match_info = []
for rule_set in match:
for hit in rule_set.strings:
match_info.append({
'file_name': file_path,
'rule_name': rule_set.rule,
'rule_tag': ",".join(rule_set.tags),
'hit_offset': hit[0],
'rule_string': hit[1],
'hit_value': hit[2]
})
return match_info
def write_stdout(columns, match_info):
for entry in match_info:
for col in columns:
print("{}: {}".format(col, entry[col]))
print("=" * 30)
Cuối cùng, chúng tôi sẽ xác định một phương thức sẽ ghi đầu ra vào tệp CSV, như được hiển thị bên dưới:
def write_csv(outfile, fieldnames, data):
with open(outfile, 'w', newline="") as open_outfile:
csvfile = csv.DictWriter(open_outfile, fieldnames)
csvfile.writeheader()
csvfile.writerows(data)
Sau khi bạn chạy tập lệnh trên thành công, chúng tôi có thể cung cấp các đối số thích hợp tại dòng lệnh và có thể tạo báo cáo CSV.