Mục lục bài viết || Contents of the article

    Ở các bài trước Tôi đã giới thiệu đến các bạn một loạt các bài viết liên quan đến mã độc như hiểm họa của mã độc đến an ninh mạng đồng thời cũng giới thiệu cho các bạn về các phương pháp phân tích mã độc. Ở chủ đề lần này xin tiếp tục gửi đến các bạn chủ đề:”Cấu trúc PE & COFF File và ý nghĩa trong việc phân tích mã độc”. 

    Sau đây tôi sẽ trình bày cho các bạn những thông tin cần lưu ý khi làm việc với PE file và đặc biệt là ý nghĩa khi sử dụng cấu trúc PE file trong quá trình phân tích mã độc. Bài viết này tôi sẽ chia làm 03 nội dung chính:

    • Tầm quan trọng của PE & COFF file
    • Cấu trúc PE & COFF file
    • Ý nghĩa trong quá trình phân tích mã độc

    Trong đó, tôi sẽ cố gắng kết hợp phân tích cấu trúc PE và COFF file trên cả hai nền tảng 64 bit và 32 bit. Qua đó, các bạn sẽ thấy được sự khác biệt khi làm việc trên 2 nền tảng này.

    Cấu trúc 1

    Tầm quan trọng của PE và COFF file

    Như chúng ta đã biết, virus nói chung và mã độc nói riêng chủ yếu tập trung trên hệ điều hành Windows. Cấu trúc các file thực thi hoặc các file đối tượng (COM) trên windows được xây dựng trên cấu trúc PE và COFF file.

    Định dạng này được hệ điều hành sử dụng để khởi tạo môi trường, cung cấp các thư viện cần thiết và tiến hành thực thi chương trình.

    Định dạng này được các chương trình nén, đóng gói (pack/unpack, archive/unarchiv, compress) dữ liệu hoặc đóng gói mã thực thi.

    Do đó, hiểu được cấu trúc và cách vận hành sẽ giúp quá trình phân tích mã độc nhanh và hiệu quả hơn

    Cấu trúc PE file

    cấu trúc 2

    Hình 1. Cấu trúc PE file (32 bit)

    cấu trúc3

    Hình 2. Cấu trúc COFF file (32 bit)

    Hai hình vẽ trên phần nào giúp các bạn hình dung được phần nào hai loại cấu trúc file PE và COFF. Sự khác biệt nằm ở phần trên Section Headers. Trong khi PE file gồm nhiều thành phần khác nhau thì COFF file chỉ gồm MS COFF Header.

    Tôi sử dụng PEInsider để xem nội dung file calc.exe. Bạn cũng có thể sử dụng PEInsider để xem cấu trúc của các file .DLL, file COM…

    cấu trúc 4

    Cấu trúc PE file của ứng dụng calc.exe trong PEInsider.

    Như trong hình trên các bạn có thể thấy trình tự từ trên xuống dưới có Dos Header, Rich Signature, Nt Headers (PE Header), Section Headers và một loại các thư mục liên quan khác.

    Rich Signature là phần không nằm trong tài liệu chính thống. Phần này được sinh ra bởi trình biên dịch của Microsoft và chỉ có trong các chương trình được build bằng trình biên.

    dịch của Microsoft, nằm giữa Dos Stub và PE Header chứa thông tin liên quan tới trình biên dịch mà không phải thông tin quan trọng, chúng ta có thể bỏ qua trường này.

    Dos Header là phần bắt đầu của PE file. Phần này gồm 64 bytes, các thành phần của Dos Header như sau:

    struct IMAGE_DOS_HEADER

    {

    WORD e_magic;          // Magic number

    WORD e_cblp;           // Bytes on last page of file

    WORD e_cp;             // Pages in file

    WORD e_crlc;           // Relocations

    WORD e_cparhdr;        // Size of header in paragraphs

    WORD e_minalloc;       // Minimum extra paragraphs needed

    WORD e_maxalloc;       // Maximum extra paragraphs needed

    WORD e_ss;             // Initial (relative) SS value

    WORD e_sp;             // Initial SP value

    WORD e_csum;           // Checksum

    WORD e_ip;             // Initial IP value

    WORD e_cs;             // Initial (relative) CS value

    WORD e_lfarlc;        // File address of relocation table

    WORD e_ovno;          // Overlay number

    WORD e_res[4];        // Reserved words

    WORD e_oemid;         // OEM identifier (for e_oeminfo)

    WORD e_oeminfo;       // OEM information; e_oemid specific

    WORD e_res2[10];      // Reserved words

    DWORD   e_lfanew;     // File address of new exe header

    };

    Trong phần này, thông thường chúng ta không quan tâm quá nhiều. Chúng ta thường để ý tới phần e_magic và e_lfanew.

    • e_magic: giá trị text “MZ”, thường gọi là chữ kí của file PE. Đây là viết tắt tên một trong những người quan trọng tạo ra hệ điều hành MS-DOS.
    • e_lfanew: nằm ở cuối cùng của Dos Header, đây là địa chỉ tương đối của PE header so với đầu file.

    Ngoài ra, còn một số trường khác liên quan tới giá trị khởi tạo khi file được load lên bộ nhớ: e_ss, e_sp, e_ip, e_cs.

    Tiếp theo là phần File Header, File Header gồm 03 phần chính: Microsoft MS-DOS stub, PE signature, COFF file header và optional header.

    MS-DOS Stub là ứng dụng MS-DOS, thực thi và in ra dòng chữ “This program cannot be run in DOS mode”.

    Signature nằm ở offset 0x3C sau MS-DOS stub, đây là 4 bytes chữ kí xác định định dạng một file PE, giá trị: “PE\0\0”.

    COFF File Header gồm 20 bytes với thứ tự và các trường như sau:

    Offset Kích thước Tên trường Mô tả
    0 2 Machine Giá trị xác định loại máy mà file được build.
    2 2 NumberOfSections Số lượng section, số này sẽ chỉ ra kích thước của bảng section.
    4 4 TimeDateStamp 32 bit thấp của số giây tính từ 00:00 1/1/1970 theo thời gian tạo ra file.
    8 4 PointerToSymbolTable Vị trí offset của bảng COFF symbol hoặc bằng 0 nếu ko có bảng này.
    12 4 NumberOfSymbols Số lượng đầu vào của bảng symbol.
    16 2 SizeOfOptionalHeader Kích thước của Optional header, trường này quan trọng đối với file thực thi.
    18 2 Characteristics Giá trị là cờ xác định thuộc tính của file.

    Optional Header: là phần tiếp sau COFF File Header, phần này gồm 224 bytes (PE32) và 240 bytes (PE32+). 8 trường đầu tiên trong Optional Header là các trường cố định. Các trường sau thay đổi tùy thuộc vào loại file.

    Vị trí Kích thước Tên trường Mô tả
    0 2 Magic Số nguyên không dấu xác định trạng thái của file.

    • 0x10B: file thực thi thông thường.
    • 0x107: ROM image.
    • 0x20B: file thực thi PE32+
    2 1 MajorLinkerVersion Số phiên bản chính của linker.
    3 1 MinorLinkerVersion Số phiên bản phụ của linker.
    4 4 SizeOfCode Kích thước của section .text hoặc tổng kích thước của các section .text.
    8 4 SizeOfInitializedData Kích thước của section khởi tạo hoặc tổng kích thước.
    12 4 SizeOfUninitializedData Kích thước của phần dữ liệu chưa khởi tạo (BSS), hoặc tổng của tất cả các phần nếu có nhiều phần BSS.
    16 4 AddressOfEntryPoint Địa chỉ của điểm bắt đầu chương trình, chính là điểm mà chương trình bắt đầu được thực thi.
    20 4 BaseOfCode Địa chỉ liên quan tới image base của điểm bắt đầu của code section khi nó được nạp lên bộ nhớ.

    File PE32 sẽ có thêm một phần không có trong PE32+ là BaseOfData, phần này có kích thước 4 bytes, theo ngay sau BaseOfCode.

    Tiếp theo là 21 trường thuộc phần mở rộng của COFF Optional Header. Các trường này chứa các thông tin cần thiết phục vụ linker và loader trên Windows. Danh sách các trường: ImageBase, SectionAlignment, FileAlignment, MajorOperatingSystemVersion, MinorOperatingSystemVersion, MajorImageVersion, MinorImageVersion, MajorSubsystemVersion, MinorSubsystemVersion, Win32VersionValue, SizeOfImage, SizeOfHeaders, CheckSum, Subsystem, DllCharacteristics, SizeOfStackReserve,

    SizeOfStackCommit, SizeOfHeapReserve, SizeOfHeapCommit, LoaderFlags, NumberOfRvaAndSizes.

     

    Vị trí (PE32/ PE32+) Kích thước (PE32/ PE32+) Tên trường Mô tả
    28/24 4/8 ImageBase Địa chỉ của byte đầu tiên của image khi được load lên bộ nhớ. Giá trị này phải chia hết cho 64K. Với mỗi hệ điều hành sẽ có giá trị mặc định khác nhau.
    32/32 4 SectionAlignment Phần liên kết các section trong bộ nhớ, tức là một section luôn luôn được bắt đầu bằng bội số của sectionAlignment. Ví dụ: sectionAlignment là 1000h, section đầu tiên bắt đầu ở vị trí 401000h và kích thước là 10h, section tiếp theo sẽ bắt đầu tại địa chỉ 402000h.
    36/36 4 FileAlignment Phần liên kết các section trong file. Tương tự như SectionAlignment nhưng áp dụng với file.
    40/40 2 MajorOperatingSystemVersion Số phiên bản chính của hệ điều hành yêu cầu.
    42/42 2 MinorOperatingSystemVersion Số phiên bản phụ của hệ điều hành yêu cầu.
    44/44 2 MajorImageVersion Số hiệu phiên bản chính của image.
    46/46 2 MinorImageVersion Số hiệu phiên bản phụ của image.
    48/48 2 MajorSubsystemVersion Số phiên bản chính của hệ thống subsystem.
    50/50 2 MinorSubsystemVersion Số phiên bản phụ của hệ thống subsystem.
    52/52 4 Win32VersionValue Phần dành riêng.
    56/56 4 SizeOfImage Kích thước theo bytes của image, bao gồm tất cả headers khi image được load lên bộ nhớ. Giá trị này phải là bội số của SectionAlignment.
    60/60 4 SizeOfHeaders Kích thước của MS-DOS stub, PE header và section header làm tròn ra số chia hết cho  FileAlignment.
    64/64 4 CheckSum Checksum của file.
    68/68 2 Subsystem Sybsystem được yêu cầu để thực thi file.
    70/70 2 DllCharacteristics
    72/72 4/8 SizeOfStackReserve Kích thước của stack được dự trữ.
    76/80 4/8 SizeOfStackCommit Kích thước của stack dùng để cam kết.
    80/88 4/8 SizeOfHeapReserve Kích thước khai báo không gian bộ nhớ heap.
    84/96 4/8 SizeOfHeapCommit Kích thước không gian bộ nhớ heap dùng để cam kết.
    88/104 4 LoaderFlags Phần dành riêng.
    92/108 4 NumberOfRvaAndSizes Số lượng đầu vào của data-directory.

    Cuối cùng là phần DataDirectory, là một mảng gồm 16 cấu trúc IMAGE_DATA_DIRECTORY, mỗi cấu trúc liên quan tới 1 cấu trúc dữ liệu trong PE file.

    typedef struct _IMAGE_DATA_DIRECTORY {
       DWORD   VirtualAddress;
       DWORD   Size;
    } IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;

    Chi tiết các bạn có thể tham khảo thêm tại: PE Format

    Phần tiếp theo là bảng Section thuộc Section Headers. Số lượng đầu vào của bảng chính bằng giá trị của trường NumberOfSections trong File Header. Mỗi section Header gồm 40 bytes với các trường:

    Vị trí Kích thước Tên trường Mô tả
    0 8 Name 8 byte tên section
    8 4 VirtualSize Kích thước khi được load lên bộ nhớ.
    12 4 VirtualAddress Địa chỉ byte đầu tiên của section tương ứng với Image base khi section được load lên bộ nhớ (File thực thi).
    16 4 SizeOfRawData Kích thước trên ổ đĩa.
    20 4 PointerToRawData Con trỏ tới trang đầu tiên của section với COFF file.
    24 4 PointerToRelocations Con trỏ file tới vị trí cấp phát mới cho các section.
    28 4 PointerToLinenumbers Con trỏ bắt đầu nhập số dòng cho section.
    32 2 NumberOfRelocations Số lượng section cần thực hiện cấp phát lại.
    34 2 NumberOfLinenumbers Số lượng đầu vào line-number cho section.
    36 4 Characteristics Giá trị cờ xác định đặc tính của section.

    Ngoài ra, còn có các phần khác: Section Data, COFF Relocations… Các bạn có thể tìm hiểu thêm tại mục: Other Contents of the file

    Chúng ta có thể thấy có rất nhiều trường trong cấu trúc phức tạp của định dạng PE. Như vậy, khi phân tích mã độc thì đâu là các trường chúng ta cần quan tâm?

    Sau đây, tôi xin tổng hợp lại một số trường mà chúng ta cần lưu ý trong quá trình phân tích file PE nói chung cũng như phân tích mã độc nói riêng.

    • Trong phần DOS Header, chúng ta cần lưu ý tới 02 trường: e_magic và e_lfanew.
    • Trong phần COFF File Header, chúng ta cần lưu ý tới trường: NumberOfSections.
    • Trong phần Optional Header, chúng ta cần quan tâm tới một số trường: AddressOfEntryPoint (RVA), ImageBase, SectionAlignment, FileAlignment, SizeOfImage, SizeOfHeaders và DataDirectory.
    • Cuối cùng, trong bảng section, một số trường cần quan tâm: VirtualSize, VirtualAddress, SizeOfRawData, PointerToRawData, Characteristics.

    Ngoài ra, chúng ta cũng cần quan tâm tới vị trí tương đối của các trường và kích thước tương ứng của chúng trên PE file.

    Vậy tại sao các thành phần trên có ý nghĩa quan trọng đối với việc phân tích file PE và đặc biệt là phân tích mã độc?

    • Trước tiên, nắm bắt được cấu trúc PE file chúng ta sẽ biết được cách thức hệ điều hành quản lí file, quản lí chương trình, nạp chương trình lên bộ nhớ, thực thi chương trình, vị trí bắt đầu thực thi.
    • Hiểu cơ chế thực thi của hệ điều hành từ đó chúng ta có thể thay đổi, chỉnh sửa file PE để được thực thi các phần như ý muốn.
    • Nắm bắt được cấu trúc, vị trí tương đối và kích thước các phần sẽ giúp quá trình phân tích mã độc trở lên nhanh chóng hơn, chúng ta sẽ dễ dàng phát hiện cách thức mã độc thực hiện tác động lên một file. Đặc biệt là đối với virus (Mã độc có chức năng lây nhiễm).

    Như vậy, trong bài này tôi đã giới thiệu sơ bộ cho các bạn các thành phần quan trọng của cấu trúc PE file. Tôi cũng đã khái quát một số thành phần quan trọng mà chúng ta cần hết sức lưu ý trong quá trình phân tích file PE nói chung và phân tích mã độc nói riêng.

    Do không có thời gian đi sâu hơn nên tôi hy vọng các kiến thức cơ bản này sẽ giúp các bạn sẽ tiếp tục nghiên cứu sâu hơn nữa về PE Format để phục vụ cho loạt bài sắp tới khi chúng ta đi sâu hơn vào quá trình phân tích mã độc.

    XEM THÊM: Một số công cụ kiểm tra mã độc website được chuyên gia tin dùng.

    Theo chuyên gia an ninh mạng: Bùi Đình Cường

     

    Bài viết đề xuất || Recommended
    1. Tình hình tấn công mạng nhắm vào blockchain năm 2020 2020 là một năm đầy thử thách với nền kinh tế nói chung và ngành an ninh mạng nói riêng. Dịch bệnh...
    Kiến thức | 15/05/2021
    Lỗ hổng bảo mật có thể xuất hiện bất cứ lúc nào trên hệ thống mạng nội bộ. Qua các lỗ hổng này, tin tặc có thể đi vào hệ thống để lấy cắp...
    Hiện nay, blockchain được coi là công nghệ chìa khóa cho chuyển đổi số. Nhờ tính minh bạch và bảo mật cao, blockchain không chỉ được ứng dụng trong lĩnh...