Trong bài blog Bring Your Own Vulnerability Drivers - Hướng tấn công mới vào những tài nguyên cũ, chúng ta đã có cái nhìn tổng quan về tình hình sử dụng các driver lỗi thời có thể bị lợi dụng để khai thác hệ thống Windows. Bài viết này sẽ đi sâu vào một kỹ thuật thường gặp, thuộc dòng nâng quyền (privilege escalation) để triển khai tấn công ấy: sử dụng cấu trúc EPROCESS.
Lưu ý: Các mô tả dưới đây chỉ nhằm phục vụ nghiên cứu và kiểm thử, phòng thủ hệ thống. Tác giả không chịu trách nhiệm với mọi hành vi sử dụng các tri thức này để thực hiện hoạt động tấn công phá hoại.
1. Khái quát về EPROCESS
Trong Windows, có 2 thành phần quan trọng đảm nhiệm quản lý các tiến trình (process): Executive subsystem (lớp thực thi) và kernel. Executive subsystem nằm ở tầng cao hơn trong hệ điều hành, cung cấp các service cần thiết cho các đối tượng như kernel, device driver, và cả các tiến trình user-mode. Executive subsystem chịu trách nhiệm quản lý tiến trình, bộ nhớ, I/O và bảo mật.
Bên cạnh đó, kernel là cốt lõi của hệ thống, tương tác trực tiếp với các phần cứng và cung cấp các service cấp thấp. Bên cạnh việc quản lý tài nguyên cho các phần cứng, kernel cũng đảm bảo bảo mật với vai trò như một thành phần trung gian giao tiếp giữa hệ thống và phần cứng
Tương ứng với hai thành phần này là 2 cấu trúc đại diện cho tiến trình: EPROCESS (Executive Process Structure) và KPROCESS (Kernel Process Structure). EPROCESS chứa các thông tin quan trọng về tiến trình, bao gồm: image, security context, cấp phát bộ nhớ và các handles tới tài nguyên. EPROCESS tham gia vào quá trình quản lý tiến trình, context-switch, kiểm soát bảo mật và quyền truy cập, quản lý tài nguyên và giao tiếp giữa các tiến trình (interprocess communication).
KPROCESS lại lưu thông tin của tiến trình liên quan tới kernel, bao gồm: process ID, danh sách các thread, thông tin cấp phát tài nguyên, và trạng thái của processor. Mỗi tiến trình đều có EPROCESS và KPROCESS, và chúng không tồn tại độc lập. KPROCESS là trường đầu tiên trong EPROCESS dưới tên Pcb, cho phép các tiến trình khác truy cập vào thông tin kernel của tiến trình hiện tại khi cần thiết.

Các trường và vị trí cụ thể của EPROCESS thay đổi qua các version của Windows. Đây là cấu trúc của EPROCESS trong Windows 10.
EPROCESS là cấu trúc quan trọng trong việc lợi dụng triển khai các kỹ thuật tấn công nâng quyền hướng tới các driver lỗi thời. Ý tưởng chính là tìm tới Access Token và lợi dụng token này để thực hiện mục tiêu.
2. Kỹ thuật “cướp token” (Token Stealing)
2.1. Một số thành phần cần chú ý để triển khai kỹ thuật
Để triển khai Token stealing, chúng ta cần chú ý tới một số thành phần sau trong EPROCESS
UniqueProcessId: PID của process
ActiveProcessLink: Trỏ tới một Doubly linked list kết nối tất cả các cấu trúc EPROCESS đang tồn tại trong hệ thống.

Token: Một cấu trúc _EX_FAST_REF lưu một con trỏ tới Access Token và một Reference counter đếm số lượng các tham chiếu tới token ở hiện tại.
//0x8 bytes (sizeof)
struct _EX_FAST_REF
{
union
{
VOID* Object; //0x0
ULONGLONG RefCnt:4; //0x0, least significat 4 bits are the reference count
ULONGLONG Value; //0x0
};
};
2.2. Ý tưởng
Security token của EPROCESS biểu diễn security context và các quyền hạn gắn với process đó. Để nâng quyền cho một process, chúng ta sẽ thay đổi security token này để có được quyền hạn cao hơn. Đối với Token stealing, chúng ta sẽ thay đổi con trỏ Token hiện tại để trỏ tới SYSTEM token nằm trong EPROCESS của SYSTEM Process.
2.3. Triển khai
Phần dưới đây trình bày khái quát các bước để triển khai ý tưởng trên:
Bước 1: Tìm EPROCESS của SYSTEM Process
Tại kernel, EPROCESS của SYSTEM Process có thể được tìm thấy nhờ sử dụng PsInitialSystemProcess. Vì đây là một hàm tại kernel mode, ở vị trí user mode, chúng ta có thể sử dụng hàm này bằng cách tìm tới địa chỉ của nó. Địa chỉ của PsInitialSystemProcess được tính bằng Kernel Base Address + PsInitialSystemProcessOffset
Bước 2: Tìm tới Token của SYSTEM Process
Bước này có thể được triển khai dễ dàng khi nắm rõ cấu trúc EPROCESS của phiên bản Windows hiện tại
Bước 3: Tìm tới EPROCESS của process đang cần nâng quyền
Từ SYSTEM EPROCESS, tìm tới ActiveProcessLinks và duyệt cho tới khi thấy EPROCESS của process cần nâng quyền
Bước 4: Thay thế Token của process cần nâng quyền bằng Token của SYSTEM
Để triển khai bước này, cần làm một số thao tác như sau:
- Lấy địa chỉ của SYSTEM Process Token (lấy được từ bước 2), thực hiện AND 0xFFFFFFFFFFFFFFF0 để 0-hóa Reference count
- Ghi Reference count của Token của process muốn nâng quyền vào Reference count của Token của SYSTEM process
- Ghi lại giá trị SYSTEM process Token đã cập nhật vào Token của process muốn nâng quyền.
3. Kỹ thuật chỉnh sửa quyền hạn (Modifying Token Privileges)
3.1 Một số thành phần cần chú ý để triển khai kỹ thuật
Cấu trúc _EX_FAST_REF.Object và _EX_FAST_REF.Value thực ra chính là _TOKEN với 4 bit cuối là giá trị của _EX_FAST_REF.RefCnt. Khi 0-hóa 4 bit cuối (hay 0-hóa số cuối) của địa chỉ _EX_FAST_REF.Object, chúng ta sẽ có được địa chỉ tới _TOKEN của process. Đây là cấu trúc của _TOKEN trong phiên bản Windows 10 mới nhất.
3.2 Ý tưởng
Trường Privileges trong _TOKEN chứa các quyền hạn của process có _TOKEN đó. Trong đó, trường Present mô tả các quyền mà process được cấp, và Enabled mô tả các quyền mà process được sử dụng (Process có thể được cấp quyền nhưng không được quyền sử dụng). Nếu chỉnh sửa được 2 trường này, chúng ta có thể thay đổi quyền hạn của process.
3.3 Triển khai
Với mô tả như trên, chúng ta có thể tận dụng kỹ thuật triển khai tại Token Stealing để tìm tới _TOKEN của process muốn chỉnh sửa quyền, sau đó chỉnh sửa hai trường Present và Enabled cho phù hợp. Đối với SYSTEM Process, giá trị của hai trường này sẽ là 0x0000001ff2ffffbc.
4. Một số lưu ý
4.1 Bề mặt tấn công
Mặc dù đối tượng tấn công là EPROCESS rất dễ gặp trong các driver, không phải driver nào cũng có thể được sử dụng làm vector tấn công. Cần lưu ý rằng hầu như các kỹ thuật tấn công đều đi từ user mode chứ không đi từ kernel mode, do đó để lợi dụng được các driver, driver phải có một phương thức giao tiếp có thể khai thác.
Đại đa số các phương thức giao tiếp với driver sẽ là IOCTL hoặc Communication Port. Các các IOCTL có gọi tới MmMapIoSpace sẽ là đối tượng có khả năng bị tấn công do MmMapIoSpace có thể được lợi dụng để tìm tới SYSTEM Process.
Cùng với đó, quá trình tấn công có thể được rút ngắn nếu process đã có quyền đọc/ghi tùy ý lên đối tượng khác. Do vậy, một driver không được cấu hình quyền hạn chính xác hoặc được để quyền Global cũng sẽ là một bề mặt tấn công lý tưởng.
4.2 Vấn đề tìm kiếm offset các hàm/trường để tấn công
Như đã nói ở mục 1, EPROCESS có cấu trúc khác nhau trên những phiên bản Windows khác nhau. Điều đó có nghĩa là nếu chỉ dựa vào offset và địa chỉ cứng, tấn công sẽ thất bại hoặc gây BSOD trên các version Windows khác nhau. Có hai hướng giải quyết vấn đề này: (1) Lưu một lookup table chứa giá trị offset của các hàm/trường của các cấu trúc qua các phiên bản EPROCESS; (2) Xây dựng kỹ thuật tìm kiếm động.
5. Phòng chống
Như đã phân tích ở 4.1, các bề mặt tấn công chủ yếu của kỹ thuật này nằm ở việc lợi dụng các giao tiếp với kernel driver và việc driver không được phân quyền hợp lý. Do vậy, các phương pháp phòng chống tấn công trước hết và đơn giản nhất chính là:
(1) Sử dụng các phương thức giao tiếp an toàn: Cấu hình IOCTL sử dụng METHOD_BUFFERED hơn là METHOD_X_DIRECT. Nếu được, nên sử dụng Communication Port (cùng với cấu hình quyền hợp lý) để thắt chặt an toàn.
(2) Khởi tạo Device Driver với security descriptor phù hợp và chỉ cho phép mở với FILE_DEVICE_SECURE_OPEN.
(3) Giới hạn các đối tượng có thể được tương tác với driver.
(4) Phân quyền truy cập tài nguyên cho driver hợp lý, tuân thủ quy tắc least privilege.
Ngoài ra, Windows có cung cấp một số giải pháp để nâng cao khả năng bảo vệ các driver khỏi các kỹ thuật tấn công trên, bao gồm Supervisor Mode Execution Prevention, Hypervisor-protected Code Integrity, PatchGuard, LSA Protection. Các tính năng này có từ Windows 10 trở lên. Do vậy, người dùng nên nâng cấp hệ điều hành lên các version Windows mới nhất để có thể được bảo vệ bởi các tính năng này.
