Bài 2: Executable File Format
Mục lục
- Compiler, Linker và Loader
- Định dạng ELF
- Định dạng PE
- Dead Space và Virus
1. Compiler, Linker và Loader
1.1 Tổng quan quy trình build
1.2 Compiler
Compiler chuyển đổi source code sang binary machine code (object code – mã máy nhị phân).
- Đầu vào: file nguồn
.c,.cpp,.s, … - Đầu ra: file object
.o(chưa thể chạy trực tiếp) - Ví dụ compiler phổ biến:
gcc,Clang,vc_compilerCTP.exe
1.3 Linker
Linker nhận các object files và library files, rồi kết hợp chúng thành một executable file hoặc library file duy nhất.
- Giải quyết các symbolic references (tham chiếu tên hàm, biến giữa các file object)
- Ví dụ:
GNU ld,lld,LINK.exe
1.4 Loader
Loader là một thành phần của hệ điều hành, chịu trách nhiệm nạp file thực thi và các thư viện vào bộ nhớ để khởi động một process mới.
Hai loại loader:
| Loại | Chức năng | Ví dụ |
|---|---|---|
| Executable loader | Nạp file thực thi | execve (system call) |
| Dynamic linking loader | Nạp thư viện động | ld-linux.so |
Các bước Loader thực hiện:
- Sao chép code (text section) và biến toàn cục (data section) từ file vào bộ nhớ
- Sao chép arguments và environment variables vào bộ nhớ
- Khởi tạo registers
- Nhảy đến điểm bắt đầu chương trình (
_startfunction) - Nạp dynamic libraries (map code của thư viện động vào bộ nhớ)
1.5 Tại sao cần định dạng file chuẩn?
Để compiler, linker và loader hoạt động đúng với nhau, chúng phải thống nhất về định dạng của object file, executable file và library file.
Các định dạng phổ biến:
| Định dạng | Hệ điều hành |
|---|---|
| ELF (Executable and Linkable Format) | Linux/Unix (*nix) |
| PE (Portable Executable) | Windows |
| Mach-O | macOS (OS X) |
2. Định dạng ELF
2.1 Tổng quan
ELF – Executable and Linkable Format là định dạng chuẩn trên các hệ thống *nix (Linux, BSD, …). ELF dùng cho:
- Executables: file chương trình có thể chạy trực tiếp
- Object files: đầu ra của compiler (
.o) - Dynamic libraries / Shared libraries: thư viện dùng chung (
.so) - Core dumps: snapshot bộ nhớ khi chương trình crash
2.2 Cấu trúc ELF
Mô tả từng thành phần:
- Thông tin nhận dạng cơ bản của file
- Bao gồm: magic number (
7f 45 4c 46), kiến trúc CPU, endianness, entry point address, vị trí của Program Header Table và Section Header Table - Công cụ xem:
readelf -h <file>
- Mô tả các segment (cách loader nạp file vào bộ nhớ)
- Chứa vị trí (địa chỉ bộ nhớ) của các section
.text,.data, … - Dùng ở runtime (loader đọc bảng này)
- Mô tả vị trí và thông tin của từng section trong file
- Dùng ở link time (linker đọc bảng này)
- Công cụ xem:
readelf -S <file>
- Chứa machine code của chương trình
- Thuộc tính: Readable + Executable (không ghi được trong điều kiện bình thường)
| Section | Nội dung |
|---|---|
.data | Biến toàn cục đã khởi tạo (initialized global variables) |
.bss | Biến toàn cục chưa khởi tạo (uninitialized global variables) |
.rodata | Dữ liệu read-only (hằng số, string literals) |
| Section | Nội dung |
|---|---|
.dynamic | Thông tin dynamic linking |
.got | Global Offset Table – hỗ trợ dynamic linking |
.init | Code khởi tạo process (chạy trước main()) |
- Thông tin để linker/loader điều chỉnh địa chỉ khi ghép các file object hoặc nạp vào bộ nhớ tại địa chỉ khác nhau
- Chứa tên và địa chỉ của các symbolic definitions (hàm exported, biến toàn cục…)
- Ví dụ: tên hàm
main,printf, … - Không được copy vào bộ nhớ khi chạy
- Thông tin phục vụ debug (mapping giữa machine code và source code)
- Không được copy vào bộ nhớ khi chạy
2.3 ELF File → Process Memory
Không phải tất cả các section trong file ELF đều được nạp vào bộ nhớ:
2.4 Section Flags – Cờ thuộc tính Section
Mỗi section có một tập flag bits xác định quyền truy cập:
| Flag | Ý nghĩa |
|---|---|
A (Alloc) | Section được cấp phát bộ nhớ khi chạy |
X (Execute) | Section chứa code có thể thực thi |
W (Write) | Section có thể ghi |
2.5 Công cụ phân tích ELF
# Xem ELF Header
readelf -h <executable>
# Xem thông tin các section
readelf -S <executable>
# Disassemble (dịch ngược machine code sang assembly)
objdump -d <executable>
# Dump hex thô
hexdump -C <executable>
# Xác định loại file
file <executable>Ví dụ output readelf -h:
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 ...
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
Type: EXEC (Executable file)
Machine: Intel 80386
Entry point address: 0x80483303. Định dạng PE
3.1 Tổng quan
PE – Portable Executable là định dạng file thực thi chuẩn trên Windows.
- PE32: dành cho code 32-bit
- PE32+: dành cho code 64-bit
- Các định dạng cũ hơn tồn tại cho 16-bit DOS và Windows 3.1
3.2 Cấu trúc PE
Các section phổ biến trong PE:
| Section | Nội dung |
|---|---|
.text | Machine code (code thực thi) |
.data | Dữ liệu read/write (biến toàn cục) |
.rdata | Dữ liệu read-only (hằng số, import table) |
.reloc | Relocation data – dùng để xây dựng IAT (Import Address Table) |
3.3 DOS Header
DOS Header là phần đầu của file PE, có từ thời DOS.
- Nếu file PE được chạy trong DOS command prompt: chương trình nhỏ trong DOS Header sẽ được thực thi
- Với hầu hết file PE32 hiện đại: DOS header chứa một đoạn code nhỏ chỉ in ra thông báo:
This application must be run from Windowsrồi thoát. Đây chỉ là thông báo tương thích ngược, không có chức năng thực sự.
4. Dead Space và Mối liên hệ với Virus
4.1 Dead Space là gì?
Dead space (không gian chết) là các vùng trống hoặc không sử dụng có mặt trong executable file.
Nguồn gốc của dead space:
- Phần đầu file ELF (padding bytes)
- Khoảng trống giữa các hàm (function padding)
- Khoảng trống giữa các section (section padding)
- Các lệnh NOP (no-operation) được chèn vào hàm để alignment
- Linker thường align các section theo page boundary (4KB hoặc 4096 bytes) để đơn giản hóa công việc của loader → sinh ra nhiều padding
4.2 Tại sao cần hiểu PE format khi học malware?
Câu hỏi: Tại sao chúng ta quan tâm đến chi tiết của PE file format?
Trả lời: Vì virus writer sẽ cố gắng lây nhiễm file PE theo cách khiến code của virus được thực thi, trong khi file PE trông vẫn bình thường từ bên ngoài. Nhiệm vụ của phần mềm diệt virus là phát hiện các virus được ngụy trang tinh vi này.
Dead space là nơi lý tưởng để giấu virus vì:
- Nằm trong file hợp lệ
- Không ảnh hưởng đến chức năng bình thường của chương trình
- Khó phát hiện nếu không phân tích kỹ cấu trúc file
Câu hỏi & Đáp án Trắc Nghiệm
Câu 1. Thứ tự đúng của quá trình build một chương trình C là?
- A. Linker → Compiler → Loader
- B. Compiler → Loader → Linker
- C. Compiler → Linker → Loader
- D. Loader → Compiler → Linker
Câu 2. Compiler tạo ra loại file nào?
- A. Executable file (
.exehoặca.out) - B. Object file (
.o) - C. Shared library (
.so) - D. Script file
Câu 3. Nhiệm vụ chính của Linker là gì?
- A. Chuyển source code sang machine code
- B. Nạp file thực thi vào bộ nhớ
- C. Kết hợp các object file và library file thành một file thực thi
- D. Khởi tạo registers trước khi chạy chương trình
Câu 4. ld-linux.so là ví dụ của loại loader nào?
- A. Executable loader
- B. Dynamic linking loader
- C. Static linker
- D. Kernel loader
Câu 5. execve là ví dụ của?
- A. Compiler
- B. Linker
- C. Executable loader (system call)
- D. Dynamic library
Câu 6. Loader thực hiện bước nào SAU KHI khởi tạo registers?
- A. Copy text section vào bộ nhớ
- B. Copy arguments vào bộ nhớ
- C. Nhảy đến hàm
_startđể bắt đầu thực thi - D. Load dynamic libraries
Câu 7. Định dạng ELF được dùng trên hệ điều hành nào?
- A. Windows
- B. macOS
- C. Linux/Unix (*nix)
- D. Android
Câu 8. ELF format được dùng cho loại file nào? (chọn tất cả đúng)
- A. Executable files
- B. Object files
- C. Dynamic libraries
- D. Core dumps
- E. Tất cả các loại trên
Câu 9. Magic number của file ELF là gì?
- A.
FF FE - B.
4D 5A(MZ) - C.
7F 45 4C 46 - D.
CA FE BA BE
Câu 10. Section .bss trong ELF chứa gì?
- A. Machine code
- B. Biến toàn cục đã khởi tạo
- C. Biến toàn cục chưa khởi tạo
- D. Dữ liệu read-only
Câu 11. Section .rodata trong ELF chứa gì?
- A. Code thực thi
- B. Dữ liệu read-only (hằng số, string literals)
- C. Biến toàn cục có thể ghi
- D. Thông tin relocation
Câu 12. Section .data trong ELF chứa gì?
- A. Code thực thi
- B. Biến toàn cục đã được khởi tạo
- C. Biến toàn cục chưa khởi tạo
- D. Thông tin debug
Câu 13. Section .got trong ELF có chức năng gì?
- A. Lưu machine code
- B. Hỗ trợ dynamic linking thông qua Global Offset Table
- C. Lưu thông tin debug
- D. Chứa biến toàn cục chưa khởi tạo
Câu 14. Section .init trong ELF chứa gì?
- A. Code khởi tạo process, chạy trước
main() - B. Dữ liệu khởi tạo biến
- C. Thông tin để linker khởi tạo symbol table
- D. Code dọn dẹp khi process kết thúc
Câu 15. Khi nạp ELF vào bộ nhớ, section nào KHÔNG được copy?
- A.
.text - B.
.data - C. Symbol table
- D.
.dynamic
Câu 16. Program Header Table trong ELF được đọc bởi ai?
- A. Compiler
- B. Linker
- C. Loader
- D. Assembler
Câu 17. Section Header Table trong ELF được đọc bởi ai?
- A. Loader
- B. Linker
- C. CPU
- D. OS kernel
Câu 18. Lệnh nào dùng để xem ELF header?
- A.
objdump -d <file> - B.
readelf -h <file> - C.
hexdump -C <file> - D.
file <file>
Câu 19. Lệnh nào dùng để disassemble (dịch ngược) một file ELF?
- A.
readelf -h - B.
hexdump -C - C.
objdump -d - D.
file
Câu 20. Flag AX trên một section ELF có nghĩa là gì?
- A. Section chỉ có thể đọc
- B. Section được cấp phát bộ nhớ và có thể thực thi
- C. Section có thể ghi và thực thi
- D. Section chứa thông tin archive
Câu 21. Virus có thể làm gì với flag bits của section ELF để lây nhiễm hiệu quả hơn?
- A. Xóa toàn bộ flag bits
- B. Sửa flag bits để biến section
.textthành writable, từ đó ghi code độc hại vào - C. Thêm flag bits để tăng kích thước section
- D. Copy flag bits sang section khác
Câu 22. Điều gì thực sự xác định quyền truy cập (read/write/execute) của một section ELF?
- A. Tên của section (
.text,.data, …) - B. Vị trí section trong file
- C. Flag bits của section
- D. Kích thước của section
Câu 23. PE format là định dạng file thực thi của hệ điều hành nào?
- A. Linux
- B. macOS
- C. Windows
- D. FreeBSD
Câu 24. PE32+ dùng cho loại code nào?
- A. 16-bit
- B. 32-bit
- C. 64-bit
- D. 128-bit
Câu 25. Magic number của file PE (Windows executable) là gì?
- A.
7F 45 4C 46 - B.
4D 5A(MZ) - C.
CA FE BA BE - D.
FF D8 FF
Câu 26. DOS Header trong file PE có chức năng gì khi chạy trên DOS?
- A. Không làm gì cả
- B. Thực thi một đoạn code nhỏ (thường in thông báo lỗi)
- C. Load Windows kernel
- D. Khởi tạo registry
Câu 27. Section .rdata trong PE chứa gì?
- A. Code thực thi
- B. Dữ liệu read/write
- C. Dữ liệu read-only (hằng số, import table)
- D. Relocation data
Câu 28. Section .reloc trong PE dùng để làm gì?
- A. Lưu code thực thi
- B. Chứa relocation data để xây dựng IAT (Import Address Table)
- C. Lưu debug symbols
- D. Chứa thông tin về version của file
Câu 29. Dead space trong executable file bao gồm những gì?
- A. Chỉ khoảng trống giữa các section
- B. Chỉ NOP instructions
- C. Khoảng trống đầu file, giữa các hàm, giữa các section, NOP instructions, và padding do alignment
- D. Chỉ padding do page alignment
Câu 30. Tại sao linker align các section theo page boundary?
- A. Để giảm kích thước file
- B. Để đơn giản hóa công việc của loader
- C. Để tăng tốc độ compiler
- D. Để tương thích với các hệ điều hành cũ
Câu 31. CIH virus (Chernobyl) sử dụng kỹ thuật nào để lây nhiễm và khó bị phát hiện?
- A. Mã hóa toàn bộ file
- B. Thêm section mới vào PE file
- C. Chia nhỏ bản thân và giấu trong dead space giữa các PE section
- D. Thay thế hoàn toàn file gốc
Câu 32. Tại sao dead space là vị trí lý tưởng để giấu virus?
- A. Vì nó dễ dàng bị phát hiện
- B. Vì nó nằm trong file hợp lệ, không ảnh hưởng chức năng bình thường, khó phát hiện
- C. Vì nó luôn được thực thi khi chương trình chạy
- D. Vì nó có nhiều không gian lưu trữ
Câu 33. Mach-O là định dạng file thực thi của hệ điều hành nào?
- A. Linux
- B. Windows
- C. macOS (OS X)
- D. Android
Câu 34. Trong ELF, PIC/PIE là gì và tại sao liên quan đến địa chỉ bộ nhớ?
- A. PIC/PIE là loại virus đặc biệt
- B. PIC (Position Independent Code) / PIE (Position Independent Executable) cho phép code chạy ở bất kỳ địa chỉ nào, thường kết hợp với ASLR
- C. PIC/PIE là loại section đặc biệt trong ELF
- D. PIC/PIE là công cụ phân tích ELF
Câu 35. ASLR có liên hệ gì đến địa chỉ của các section trong ELF?
- A. ASLR cố định địa chỉ các section
- B. ASLR ngẫu nhiên hóa địa chỉ bộ nhớ mỗi lần chạy, làm cho địa chỉ trong ELF không còn chính xác tuyệt đối
- C. ASLR xóa section header table
- D. ASLR mã hóa nội dung các section
Câu 36. Lệnh file <executable> có tác dụng gì?
- A. Liệt kê các file trong thư mục
- B. Xác định loại file (ELF, PE, script, …)
- C. Hiển thị nội dung file dưới dạng hex
- D. Disassemble file
Câu 37. Trong quá trình dynamic linking, thư viện (.so) được nạp vào bộ nhớ khi nào?
- A. Khi compile
- B. Khi link
- C. Khi loader khởi động process
- D. Thư viện không bao giờ nạp vào bộ nhớ
Câu 38. Điểm vào (entry point) của chương trình ELF thường là hàm gì?
- A.
main() - B.
_start - C.
init() - D.
entry()
Câu 39. Symbol table trong ELF chứa thông tin gì?
- A. Machine code của chương trình
- B. Tên và địa chỉ của các symbolic definitions như tên hàm, biến toàn cục
- C. Thông tin về dynamic libraries cần nạp
- D. Dữ liệu runtime của chương trình
Câu 40. Core dump file trong ELF chứa gì?
- A. Chỉ chứa source code
- B. Snapshot của bộ nhớ process tại thời điểm crash
- C. Log của toàn bộ quá trình thực thi
- D. Thông tin về cấu hình hệ thống
Câu 41. Sự khác biệt chính giữa static linking và dynamic linking là gì?
- A. Static linking nhanh hơn dynamic linking
- B. Static linking nhúng toàn bộ thư viện vào executable; dynamic linking chỉ tham chiếu, thư viện nạp lúc runtime
- C. Static linking chỉ dùng trên Linux; dynamic linking chỉ dùng trên Windows
- D. Không có sự khác biệt
Câu 42. Trong phân tích malware, tại sao cần biết chi tiết về PE/ELF format?
- A. Để viết phần mềm nhanh hơn
- B. Vì virus lợi dụng cấu trúc file format để ẩn mình; hiểu format giúp phát hiện virus tinh vi
- C. Để tối ưu hóa compiler
- D. Để thiết kế CPU hiệu quả hơn
Câu 43. Khi nào địa chỉ của section trong ELF được cố định (không thay đổi giữa các lần chạy)?
- A. Luôn luôn cố định
- B. Khi không dùng PIC/PIE và ASLR bị tắt
- C. Khi dùng ASLR
- D. Khi dùng dynamic linking
Câu 44. Trong ELF, sự khác biệt giữa “section” và “segment” là gì?
- A. Không có sự khác biệt
- B. Section là góc nhìn của linker (link time); segment là góc nhìn của loader (runtime)
- C. Section lớn hơn segment
- D. Segment chỉ tồn tại trong PE, không có trong ELF
Câu 45. IAT (Import Address Table) trong PE dùng để làm gì?
- A. Lưu danh sách các function exported của file PE
- B. Lưu địa chỉ thực tế của các hàm được import từ DLL khi chạy
- C. Quản lý bộ nhớ heap
- D. Lưu thông tin debug
Câu 46. Lệnh readelf -S <file> hiển thị thông tin gì?
- A. ELF header
- B. Thông tin từng section (tên, địa chỉ, kích thước, flags)
- C. Disassembly code
- D. Dynamic linking dependencies
Câu 47. Kích thước của file PE bị nhiễm CIH virus so với file gốc như thế nào?
- A. Lớn hơn đáng kể
- B. Nhỏ hơn
- C. Gần như không thay đổi
- D. Gấp đôi
Câu 48. Trong ELF, entry point address trong ELF header chỉ đến đâu?
- A. Hàm
main() - B. Địa chỉ đầu tiên của section
.text - C. Địa chỉ của hàm
_start(điểm bắt đầu thực thi) - D. Địa chỉ của dynamic linker
Câu 49. Tại sao antivirus không thể chỉ dựa vào tên section để xác định quyền của nó?
- A. Tên section quá dài
- B. Vì virus có thể sửa flag bits mà không đổi tên section, quyền thực sự do flag bits quyết định
- C. Vì ELF không có tên section
- D. Vì tên section bị mã hóa
Câu 50. Bộ ba công cụ cơ bản để phân tích file ELF trên Linux là?
- A.
gcc,ld,execve - B.
readelf,objdump,hexdump - C.
vim,nano,gedit - D.
ps,top,htop