itprofes
Bạn có muốn phản ứng với tin nhắn này? Vui lòng đăng ký diễn đàn trong một vài cú nhấp chuột hoặc đăng nhập để tiếp tục.

Theo dõi tiến trình

Go down

Theo dõi tiến trình Empty Theo dõi tiến trình

Bài gửi  admin on 11/5/2010, 10:53 am

1. Đặt vấn đề
Với các sản phẩm phần mềm bảo mật như Personal Firewall thì việc giám sát việc tạo, hủy tiến trình là rất quan trọng trong việc phát hiện và ngăn chặn các tiến trình “độc” thực thi mã của chúng. Tuy nhiên, các tiến trình được khởi tạo và quản lý bởi hệ điều hành. Chương trình của người sử dụng ở tầng User-mode không thể can thiệp vào quá trình này. Do vậy, để có thể đạt được một kết quả khả quan, cần phải có những cơ chế tốt cho phép can thiệp vào nhân hệ điều hành và đón bắt được cách thức hệ điều hành tạo ra cũng như quản lý các tiến
trình.

2. Các nhiệm vụ chính cần giải quyết
Báo cáo này sẽ chỉ tập trung giải quyết các vấn đề chủ yếu sau:
• Đón bắt việc tạo và hủy tiến trình, tiểu trình, nạp thư viện DLL một cách Real-time
• Đón bắt việc một tiến trình chuẩn bị được tạo ra và can thiệp được vào quá trìnhnày.

3. Đón bắt việc tạo, hủy tiến trình
Trên Windows, các ứng dụng ở tầng User mode thường sử dụng hàm API CreateProcess() để tạo và thực thi một tiến trình mới. Hàm API này thực chất chỉ là một hàm trung gian chuyển lời gọi từ User mode đến hàm thực sự tạo tiến trình trong Kernel mode. Trong Kernel mode, tồn tại các hàm API có tên dạng tương tự như các hàm API trong User mode. Các hàm này được gọi là các hàm native API – NT. Ví dụ, hàm NT tương ứng của CreateProcess() là NtCreateProcess(). Windows NT trợ giúp nhiều hệ thống con (subsystem) bao gồm :Win32, POSIX và OS2. Mỗi subsystem bao gồm một tập các hàm API mà người dùng ở User mode có thể gọi để thực hiện các tác vụ mong muốn. Chẳng hạn, với Win32 subsystem, thư viện Kernel32.dll
cung cấp rất nhiều các hàm để thao tác với tiến trình, bộ nhớ, vào ra…Tuy nhiên, Kernel32.dll thực chất không phải là nhân của hệ điều hành. Nó chỉ là một lớp trung gian làm nhiệm vụ giao tiếp giữa lời gọi từ User mode vào Kernel mode. Việc chuyển lời gọi hàm này cuối cùng sẽ được thực hiện bởi các hàm trong thư viện Ntdll.dll. Hình vẽ sau minh họa quá trình route một lời gọi hàm từ User mode vào Kernel mode:
Theo dõi tiến trình Monitoringprocesses01yl9
Thư viện Ntdll.dll có thể được coi là “lá chắn” cuối cùng của tầng User mode tiếp giáp với Kernel mode. Các đoạn mã thực sự thi hành các dịch vụ của hệ điều hành nằm trong file ntoskrnl.exe. Ntdll.dll chỉ làm nhiệm vụ phơi bày một số hàm API mà ntoskrnl.exe cung cấp để cho Kernel32.dll, User32.dll, Gdi32.dll…gọi chúng. Hiểu được cơ chế ở trên, để có thể đón bắt việc tạo và hủy tiến trình một cách realtime,ta đề xuất một số giải pháp sau:
3.1. Giải pháp 1: sử dụng API hooking trong User mode
API hooking cho phép hook một hàm API mà một thư viện nào đó đã export. Để có thể hook, cần phải đặt mã của hàm hook vào trong một file DLL. Sau đó, nạp file DLL này vào tiến trình cần hook. Tiến trình cần hook chính là tiến trình đã nạp thư viện dll đã export hàm API trên. Có nhiều cách thực hiện việc hook API ở tầng user mode mà điển hình nhất là sử dụng Trampoline function (thư viện Detours đã sử dụng kĩ thuật này). Với mục đích đã đặt ra, các hàm cần hook bao gồm: CreateProcess(),WinExec(), ShellExecute(), Yield(), TerminateProcess(), ExitProcess(). Hơn nữa, cần phải hook mọi tiến
trình đang chạy nhằm phát hiện việc tạo, hủy tiến trình từ mọi tiến trình này. Điều này là không tối ưu nếu xét về góc độ hiệu năng và tính hiệu quả. Thứ nhất, việc sử dụng API hook cho toàn bộ tiến trình sẽ làm suy giảm hiệu năng hệ thống. Thứ hai, có thể tồn tại các hàm API khác dạng undocumented cũng có chức năng tạo tiến trình. Khi đó, việc hook này sẽ khôngthành công.

3.2. Giải pháp 2: Sử dụng Polling kết hợp với các hàm API liệt kê tiếntrình

Theo phương pháp này, một Thread ngầm sẽ được tạo ra. Nhiệm vụ của Thread này là liên tục capture các tiến trình của hệ điều hành nhằm phát hiện việc tạo và hủy tiến trình mới.Để capture thông tin về tiến trình, có thể sử dụng các hàm API do các thư viện psapi.dll, thư viện Tool help 32 như : EnumProcess(), CreateToolhelp32Snapshot()… Ưu điểm của phương pháp này là dễ cài đặt. Tuy nhiên, không tối ưu về hiệu năng cũng như tính realtime.
3.3. Giải pháp 3: Sử dụng API hooking trong Kernel mode

Như đã đề cập ở trên, các hàm API trong User mode chỉ thực sự là trung gian chuyển lời gọi từ User mode vào Kernel mode. Chẳng hạn, CreateProcess() thực chất sẽ gọi vào NtCreateProcess(). Do vậy, để tăng tính triệt để và thu hẹp phạm vi kiểm soát, có thể sử dụng
phương pháp Hook các hàm native API.Theo phương pháp này, hàm hook sẽ được đặt trong một Device Driver. Vai trò của Device Driver trong Kernel mode cũng tương tư như các file DLL trong User mode khi sử dụng System-wide hook. Các hàm native API liên quan đến tạo, hủy tiến trình sẽ bị hook.
Hàm hook sẽ đón bắt việc gọi đến các hàm này và trả về thông tin cho người dùng ở User mode đồng thời gọi hàm bị hook (e.g, NtCreateProcess) để tiến trình có thể tạo và hủy một cách hợp lệ.Ưu điểm của phương pháp này là có thể thu hẹp phạm vi giám sát các hàm API. Thay vì phải giám sát một số lượng lớn các hàm API tạo, hủy tiến trình ở User mode, phương pháp này chỉ giám sát một số hàm native API ở Kernel mode. Do vậy, sẽ có thể đón bắt tốt hơn việc tạo, hủy tiến trình cũng như tăng tính Real-time. Nhược điểm của phương pháp này là nếu cài đặt không tốt, có thể gây ra sự phụ thuộc qúa nhiều vào các hàm native API vốn có thể bị thay đổi bởi Microsoft trong các phiên bản khác nhau của Windows.
3.4. Giải pháp 4: Sử dụng native API tiện ích của hệ điều hành
Trong tất cả các giải pháp đưa ra, có lẽ giải pháp này sẽ mang lại hiệu quả hơn cả. Nguyên lý của giải pháp này dựa trên cơ chế sau: Windows cung cấp một số hàm API ở tầng Kernel mode hỗ trợ việc đăng ký một hàm Callback nhằm thông báo việc tạo và hủy tiến trình.Mỗi khi có một tiến trình được tạo hoặc hủy, Windows sẽ gọi hàm Callback này. Hàm Callback cần phải được đặt trong một Device Driver vì cơ chế này chỉ làm việc ở Kernel mode.Hàm mà ta vừa nêu có dạng như sau:
Tham số Remove sẽ thiết lập cơ chế Callback (FALSE) hoặc loại bỏ hàm Callback(TRUE).
Hàm Callback có dạng sau:
Trong hàm Callback này, các ham số bao gồm:

Code:
NTSTATUS PsSetCreateProcessNotifyRoutine(IN
    PCREATE_PROCESS_NOTIFY_ROUTINE Callback,IN BOOLEAN
    Remove);
    VOID ProcessCallback(IN HANDLE ParentId,
    IN HANDLE ProcessId,
    IN BOOLEAN Create);

• ParentId: ID của Process cha đã tạo hoặc hủy tiến trình
• ProcessId: ID của Process được tạo hoặc hủy
• Create: TRUE nếu Process được tạo, FALSE nếu bị hủy
Trong hàm Callback, các thông tin về tiến trình vừa tạo hoặc hủy sẽ được thông báo cho chương trình người sử dụng ở User mode biết và xử lý. Ở đây, ta sử dụng cơ chế giao tiếp sự kiện. Một đối tượng đồng bộ kiểu Event được tạo ra trong DriverEntry. Chương trình User mode sẽ lắng nghe Event này. Khi hàm Callback được gọi, Event được thiết lập trạng thái thành Signaled và chương trình User mode sẽ được thông báo để có thể gửi lệnh IOCTL vào
Driver và lấy thông tin cần thiết. Thông tin về tiến trình sẽ được lưu tạm thời trong một cấu trúc PROCESS_CALLBACK_INFO của DEVICE_EXTENSION.

Code:
 typedef struct tagProcessCallbackInfo
    {
    HANDLE hParentID;
    HANDLE hProcessID;
    BOOLEAN bCreated;
    }PROCESS_CALLBACK_INFO,*PPROCESS_CALLBACK_INFO;
    //....................
    /***********************************************/
    void ProcessCallback(IN HANDLE ParentId,
    IN HANDLE ProcessId,
    IN BOOLEAN Create)
    {
    PDEVICE_EXTENSION pDevExtension;
    // Lấy về đối tượng Device Extension từ biến toàn
    cục g_pDeviceObject.
    pDevExtension=(PDEVICE_EXTENSION)g_pDeviceObject-
    >DeviceExtension;
    // Gán thông tin tiến trình vào cấu trúc ProcessInfo
    trong Device Extension
    pDevExtension->ProcessInfo.hParentID=ParentId;
    pDevExtension->ProcessInfo.hProcessID=ProcessId;
    pDevExtension->ProcessInfo.bCreated=Create;
    // Thiết lập Event để thông báo cho User mode
    KeSetEvent( pDevExtension->KeProcessEvent,
    0,
    FALSE);
    KeClearEvent(pDevExtension->KeProcessEvent);
    }

    // Lấy về thông tin tiến trình qua IOCTL
    NTSTATUS DispatchIoctl(IN PDEVICE_OBJECT DeviceObject, IN PIRP
    Irp)
    {
    //.................
    switch(pIoStack->Parameters.DeviceIoControl.IoControlCode)
    {
    case IOCTL_GET_PROCESS_INFO:
    {
    if(pIoStack-
    >Parameters.DeviceIoControl.OutputBufferLength>=
    sizeof(PROCESS_CALLBACK_INFO))
    {
    // Set user-supplied buffer
    pProcessInfo=(PPROCESS_CALLBACK_INFO)Irp-
    >AssociatedIrp.SystemBuffer;
    // Lấy thông tin tiến trình đã lưu trong
    Device Extension và gán vào bộ đệm trả về cho User mode
    pProcessInfo->hParentID=pDevExtension-
    >ProcessInfo.hParentID;
    pProcessInfo->hProcessID=pDevExtension-
    >ProcessInfo.hProcessID;
    pProcessInfo->bCreated=pDevExtension-
    >ProcessInfo.bCreated;
    }
    break;
    }


4. Đón bắt việc tạo, hủy tiểu trình và các module
Cơ chế tương tự cũng được sử dụng để đón bắt việc tạo, hủy các tiểu trình (Thread) và nạp, hủy nạp các module DLL. Các hàm sử dụng cho việc này như sau:

Code:
 NTSTATUS
    PsSetCreateThreadNotifyRoutine(PCREATE_THREAD_NOTIFY_ROUT
    INE Callback;
    NTSTATUS
    PsSetLoadImageNotifyRoutine(PLOAD_IMAGE_NOTIFY_ROUTINE
    Callback);
    VOID ThreadCallback( IN HANDLE ProcessId,
    IN HANDLE ThreadId,
    IN BOOLEAN Create);
    VOID ImageCallback( IN PUNICODE_STRING FullImageName,
    IN HANDLE ProcessId,
    IN PIMAGE_INFO ImageInfo);


5. Đón bắt và can thiệp quá trình tạo tiến trình
Như đã phân tích ở trên, kĩ thuật hook các hàm native API tỏ ra có lợi thế trong các trường hợp này. Để đón bắt việc tạo một tiến trình và có thể can thiệp nó (hủy không cho tạo hoặc cho tiếp tục tạo tiến trình), cần phải có cơ chế hook các hàm native API có khả năng tạo tiến trình. Một ứng cử viên tiềm tàng là hàm NtCreateProcess(). Tuy nhiên, không có điều gì đảm bảo rằng có hay không một hàm khác cũng có thể tạo tiến trình. Vì vậy, cần phải hook ở mức độ hẹp hơn. Cơ chế tạo tiến trình có thể được minh họa bởi dãy các hàm sau:
Theo dõi tiến trình Monitoringprocesses02jo4
Do vậy, để có thể đón bắt ở mức hẹp hơn, ta nên hook hàm NtCreateSection(). Hàm này sẽ được gọi trước khi hàm NtCreateProcess() được gọi. Việc hook hàm NtCreateSection() được thực hiện bằng cách can thiệp vào bảng System Service Dispatch Table (bảng chứa vector đến địa chỉ các hàm thực sự cung cấp dịch vụ của hệ điều hành) và sửa đổi địa chỉ của hàm NtCreateSection() thành địa chỉ của hàm hook đặt trong Driver. Cấu trúc của bảng SSDT như sau:
Theo dõi tiến trình Monitoringprocesses03yc1
Để tiện lợi, ta định nghĩa một macro dùng cho việc lấy về địa chỉ của một hàm nativeAPI bất kỳ như sau:
NtCreateSection() NtCreateProcess() NtCreateThread() NtCreateFile()

Macro trên sẽ lấy về địa chỉ hàm _function.Các thủ tục Hook và UnHook đơn giản là thay thế địa chỉ hàm thực bởi hàm hook vàngược lại:
RealZwCreateSection là một con trỏ hàm đến hàm NtCreateSection.
Trong hàm hook, một đối tượng Event sẽ được thiết lập trạng thái signaled để thông báo cho người sử dụng và đợi ý kiến của người dùng (cho phép hoặc cấm) tiến trình thực hiện. Tùy theô kết quả trả về mà hàm hook sẽ gọi hàm gốc (cho phép) hoặc trả về STATUS_ACCESS_DENIED để báo rằng việc tạo tiến trình không được thực hiện.

Code:
  #define SYSCALL(_function) ServiceTable->ServiceTable[
    *(PULONG)((PUCHAR)_function+1)]
    NTSTATUS (*RealZwCreateSection) ( OUT PHANDLE,
    IN ULONG,
    IN POBJECT_ATTRIBUTES,
    IN PLARGE_INTEGER,
    IN ULONG,
    IN ULONG,
    IN HANDLE
    );
    void SetHook(){
    // Lưu hàm gốc
    RealZwCreateSection=SYSCALL(ZwCreateSection);
    // Thay hàm gốc bằng hàm hook
    SYSCALL(ZwCreateSection)=(PVOID)HookZwCreateSection;
    }
    void UnsetHook(){
    // Khôi phục hàm gốc
    SYSCALL(ZwCreateSection)=(PVOID)RealZwCreateSection;
    }

    NTSTATUS HookZwCreateSection(OUT PHANDLE SectionHandle,
    IN ULONG DesiredAccess,
    IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
    IN PLARGE_INTEGER MaximumSize OPTIONAL,
    IN ULONG PageAttributess,
    IN ULONG SectionAttributes,
    IN HANDLE FileHandle OPTIONAL )
    {
    //........................
    // Set event so that user can be notified
    KeSetEvent(pDevExt->KeHookEvent,
    0,
    FALSE);
    KeClearEvent(pDevExt->KeHookEvent);
    DbgPrint("Waiting for user response...\n");
    // Đợi trả lời của người dùng
    UserResponse.bResponsed=FALSE;
    while(1)
    {
    KeDelayExecutionThread(KernelMode,0,&li);
    if(UserResponse.bResponsed)
    break;
    }
    // Nếu người dùng cho phép thì gọi hàm gốc
    if(UserResponse.bAllowed)
    {
    DbgPrint("ProcMan: User responsed allow\n");
    RETURN_ORG;
    }
    // Nếu không thi trả về lỗi và hủy việc tạo tiến trình
    else
    {
    DbgPrint("ProcMan: User responsed disallow\n");
    return STATUS_ACCESS_DENIED;
    }
    return STATUS_SUCCESS;

6. Chương trình Demo
Chương trình demo được xây dựng nhằm sử dụng Driver đã tạo và minh họa kết quả. Chương trình được viết bằng Visual C++ 6.0, sử dụng MFC. Một số kết quả demo như hình chụp dưới đây:
Theo dõi tiến trình Monitoringprocesses04ou7
Hình 1: Giao diện chính
Theo dõi tiến trình Monitoringprocesses05ns2
Hình 2: Thông báo tiến trình vừa được tạo
Theo dõi tiến trình Monitoringprocesses06qr1
Hình 3:Thông báo tiến tình bị hủy
Theo dõi tiến trình Monitoringprocesses07vs4
Hình 4: Hỏi người dùng quyết định việc có tạo tiến tình hay không
Theo dõi tiến trình Monitoringprocesses08ms9
Hình 5: Không cho phép tạo tiến trình
Theo dõi tiến trình Monitoringprocesses09ya8
Hình 6: Ứng dụng xây dựng chức năng lọc chương trình dựa trên tập luật
Theo dõi tiến trình Monitoringprocesses10ie0
Hình 7: Tạo luật lọc tiến trình

7. Đánh giá kết quả
Chương trình đã được thử nghiệm trên Windows XP SP2, Windows Server 2003 Standard Edition và cho kết quả tốt. Có thể bắt được việc tạo tiến trình của bất kỳ tiến trình nào kể cả explorer.exe, task manager… Hiệu năng của hệ thống hầu như ổn định. Hướng phát triển tiếp theo sẽ bao gồm việc theo dõi các hành vi khác của tiến trình như: truy cập file, truy cập Registry, truy cập network…
admin
admin
Thiếu Úy III
Thiếu Úy III

Tổng số bài gửi : 627
Diem : 5299
Thank : 4
Join date : 24/03/2010
Đến từ : Bỉm Sơn - Thanh hóa

https://itprofes.forumvi.com

Về Đầu Trang Go down

Theo dõi tiến trình Empty Re: Theo dõi tiến trình

Bài gửi  haigaopro01 on 27/8/2011, 5:51 pm

share code đi bạn ơi Very Happy
haigaopro01
haigaopro01
Tập sự
Tập sự

Tổng số bài gửi : 1
Diem : 3380
Thank : 0
Join date : 27/08/2011

Về Đầu Trang Go down

Về Đầu Trang

- Similar topics

 
Permissions in this forum:
Bạn không có quyền trả lời bài viết