Memory Types
Các tiến trình có các loại bộ nhớ khác nhau:
- Private memory: chỉ có thể được truy cập bởi tiến trình đó.
- Mapped memory: có thể được chia sẻ giữa các tiến trình. Nó được sử dụng để chia sẻ dữ liệu giữa các tiến trình, các thư viện chia sẻ, các phân đoạn bộ nhớ (memory segments) chia sẻ và các tập tin chia sẻ. Mapped memory có thể được đọc bởi các tiến trình khác nhưng không thể được ghi bởi các tiến trình khác.
- Image memory: chứa code và dữ liệu của file thực thi.
Process Environment Block (PEB)
Chứa các thông tin liên quan đến một tiến trình chẳng hạn như các tham số của nó, thông tin khởi chạy (startup information), thông tin về heap đã được cấp phát, các DLL đã được nạp, định danh (process ID - PID) và đường dẫn đến file thực thi.
Cấu trúc của PEB trong C:
typedef struct _PEB {
BYTE Reserved1[2];
BYTE BeingDebugged;
BYTE Reserved2[1];
PVOID Reserved3[2];
PPEB_LDR_DATA Ldr;
PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
PVOID Reserved4[3];
PVOID AtlThunkSListPtr;
PVOID Reserved5;
ULONG Reserved6;
PVOID Reserved7;
ULONG Reserved8;
ULONG AtlThunkSListPtr32;
PVOID Reserved9[45];
BYTE Reserved10[96];
PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine;
BYTE Reserved11[128];
PVOID Reserved12[1];
ULONG SessionId;
} PEB, *PPEB;
Chúng ta có thể bỏ qua các thành phần có kiểu là Reserved
.
BeingDebugged
Là một cờ (với hai giá trị 1
và 0
) cho biết tiến trình có đang được debug hay không. Nó được sử dụng bởi Windows loader để xác định xem có nên chạy chương trình với debugger được gắn kèm hay không.
Ldr
Con trỏ đến cấu trúc PEB_LDR_DATA
, chứa các thông tin về các DLL đã được nạp vào tiến trình. Cụ thể hơn, PEB_LDR_DATA
chứa danh sách các DLL được nạp vào tiến trình, base address của từng DLL và kích thước của từng DLL.
Cấu trúc:
typedef struct _PEB_LDR_DATA {
BYTE Reserved1[8];
PVOID Reserved2[3];
LIST_ENTRY InMemoryOrderModuleList;
} PEB_LDR_DATA, *PPEB_LDR_DATA;
Có thể tận dụng PEB_LDR_DATA
để tìm base address của một DLL cụ thể nào đó cũng như là của các hàm ở trong không gian bộ nhớ.
ProcessParameters
Chứa các tham số command line của tiến trình. Thực chất, nó là con trỏ đến cấu trúc RTL_USER_PROCESS_PARAMETERS
:
typedef struct _RTL_USER_PROCESS_PARAMETERS {
BYTE Reserved1[16];
PVOID Reserved2[10];
UNICODE_STRING ImagePathName;
UNICODE_STRING CommandLine;
} RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS;
AtlThunkSListPtr & AtlThunkSListPtr32
Được sử dụng bởi ATL (Active Template Library) module để lưu trữ con trỏ đến một danh sách liên kết các hàm thunking. Các hàm này được dùng để gọi các hàm mà được hiện thực ở một không gian vùng nhớ khác, thường là các hàm được export bởi các DLL.
PostProcessInitRoutine
Là con trỏ đến một hàm mà sẽ được gọi bởi OS sau khi việc khởi tạo TLS (Thread Local Storage) được hoàn thành cho tất cả các thread trong tiến trình. Hàm này được sử dụng để thực hiện các bước khởi tạo bổ sung cần thiết cho tiến trình.
SessionId
Một định danh duy nhất cho session, được sử dụng để ghi lại hoạt động của người dùng trong một session.
Thread Environment Block (TEB)
Được dùng để lưu trữ thông tin của một thread. Nó chứa thông tin về môi trường của thread, security context và các thông tin liên quan. TEB được lưu ở trong thread stack và được sử dụng bởi Windows kernel để quản lý các thread.
Cấu trúc của TEB:
typedef struct _TEB {
PVOID Reserved1[12];
PPEB ProcessEnvironmentBlock;
PVOID Reserved2[399];
BYTE Reserved3[1952];
PVOID TlsSlots[64];
BYTE Reserved4[8];
PVOID Reserved5[26];
PVOID ReservedForOle;
PVOID Reserved6[4];
PVOID TlsExpansionSlots;
} TEB, *PTEB;
ProcessEnvironmentBlock (PEB)
Con trỏ đến PEB của tiến trình mà thread này thuộc về.
TlsSlots
Là nơi mà TEB dùng để lưu trữ dữ liệu của từng thread. Mỗi thread sẽ có một TEB và mỗi TEB sẽ có một mảng các TLS slot. Các ứng dụng có thể dùng các slot này để lưu trữ dữ liệu của từng thread.
TlsExpansionSlots
Là một tập các con trỏ lưu dữ liệu cục bộ của từng thread và thường được để dành cho các system DLL.
Process And Thread Handles
Tương tự với tiến trình, mỗi thread cũng có một định danh duy nhất là thread ID (TID). Giá trị này là duy nhất cho toàn bộ các thread tất cả các tiến trình.
PID và TID có thể được dùng để tạo một handle đến tiến trình hoặc thread thông qua hàm OpenProcess
và hàm OpenThread
.
Các handle nên được đóng lại khi không cần dùng nữa để tránh handle leaking (giống memory leak). Có thể đóng handle bằng cách gọi hàm CloseHandle
và truyền vào handle.
Related
list
from outgoing([[MalDev - Processes and Threads]])
sort file.ctime asc