Trao đổi với tôi

http://www.buidao.com

7/1/09

[Rootkit] Kỹ thuật biến đổi nhân của Windows – Phần 1 : trình điều khiển thiết bị

Kỹ thuật biến đổi nhân của Windows – Phần 1 : trình điều khiển thiết bị

Link gốc: http://hardsoftvn.wordpress.com/category/bai-phan-tich-h%C6%B0%E1%BB%9Bng-d%E1%BA%ABn/

-Đây là loạt bài về cách biến đổi nhân hệ điều hành cũng như cách lợi dụng nó. Lọat bài này là sự tổng hợp những kinh nghiệm của tôi trên mặt trận bảo mật và xâm nhập. Xin nói rõ là tôi cũng chỉ thừa hưởng những thành quả của những đàn anh đi trước như fuzen_op – tác giả của rootkit fu , holy_father – tác giả của rootkit ‘hacker defender’ , Greg Hoglund và Jamie Butler – tác giả của cuốn Rootkit – Subverting the Windows Kernel và nhiều nhiều nữa. Cũng xin nói thêm đây không phải là lọat bài hướng dẫn các bạn cách thức phá hoại , như tôi đã nói tốt hay xấu là do chính ở mỗi người . Ngôn ngữ được sử dụng ở đây là Delphi (7) và C (Visual C ++ 6) .

- Nhân của hệ điều hành có thể là một khái niệm mơ hồ đối với nhiều bạn . Thật ra nhân của hệ điều hành là nơi mà hệ điều hành điều khiển mọi thứ. Nhân này tọa lạc tại vòng số 0 của bộ vi xử lý (Bộ nhớ của vi xử lý Intel được chia làm 4 vòng , vòng số 0 có nhiều đặc quyền nhất và vòng số 3 có ít đặc quyền nhất). Có thể nói thêm là Windows đã dùng cách thức bảo mật của vi xử lý Intel để tạo ra cơ chế bảo mật của mình. Bộ xử lý trung tâm sẽ quyết định xem mã thực thi cuả một vật thể sẽ nằm ở vòng nào trong bộ nhớ và kiểm sóat việc di chuyển những đoạn mã này qua vòng khác. Việc di chuyển giữa các vòng chỉ có thể thực hiện bằng 1 trong 3 cách đặc biệt : dùng trình điều khiển thiết bị , sử dụng cổng gọi và khai thác lỗ hổng bảo mật . Trong phần này tôi chỉ đề cập tới trình điều khiển thiết bị – đây là cách dễ nhất nhưng cũng yếu nhất.

- Trình điều khiển thiết bị là những đoạn mã đặc biệt được hệ điều hành ưu ái cho chúng thực thi ở vòng số 0. Trình điều khiển thiết bị là cách duy nhất mà những công ty sản xuất phần cứng dùng để điều khiển thiết bị của họ (nếu Windows chưa hỗ trợ). Việc thực thi đoạn mã của mình ở vòng số 0 là một trong những niềm tự hào của bất kỳ chuyên viên bảo mật nào.Cách thức tao ra trình điều khiển thiết bị như thế nào ? Ngôn nhữ nào có thể tạo ra chúng ? Đó là hai câu hỏi thường gặp với những người mới bắt đầu. Câu trả lời là : bạn chỉ có thể sử dụng C hay Delphi (cái này rất khó, tôi đã thử và chỉ toàn thất bại ^_^) và trình biên dịch là bộ DDK (Driver Development Kit) của Microsoft. Bạn hãy tải bộ DDK này về tại địa chỉ http://www.microsoft.com/whdc/devtools/ddk/default.mspx và sau đó ta có thể bắt đầu viết trình điều khiển thiết bị .

- Bạn có thể dùng notepad để viết mã . Đây là một ví dụ về trình điều khiển thiết bị :

////////////////////////////////////////////////////////////////////////////////////////


#include “ntddk.h”


VOID OnUnload( IN PDRIVER_OBJECT DriverObject )

{

DbgPrint(”Goodbye cruel world !\n”);


}


NTSTATUS DriverEntry( IN PDRIVER_OBJECT theDriverObject,

IN PUNICODE_STRING theRegistryPath )

{

// in ra man hinh 1 dong chu. Ban co the dung DebugView cua SysInternals de xem.

DbgPrint(”From Here We Rule ! VietNam Rule !”);

// chi dinh ham de tiep nhan viec ngung trinh dieu khien thiet bi

theDriverObject->DriverUnload = OnUnload;


return STATUS_SUCCESS;

}

/////////////////////////////////////////////////////////////////////////////////////////


-Đối với những bạn đã rành về C thì đọan mã này quá đơn giản. Bạn hãy lưu lại với tên sample1-1.c vào thư mục của bộ DDK là : ….\DDK\sample1-1 (trong máy tôi là E:\Program Files\DDK) . Sau đó hãy tạo ra 2 tập tin với tên makefile và sources (không có phần đuôi mở rộng) với nội dung lần lượt là :


!INCLUDE $(NTMAKEENV)\makefile.def



TARGETNAME=Sample1-1

TARGETPATH=obj

TARGETTYPE=DRIVER


C_DEFINES=$(C_DEFINES)

SOURCES=sample1-1.c

RELEASETYPE=DDK


Sau đó lưu vào ….\DDK\sample1-1 (chung thư mục với sample1-1.c) . Bây giờ hãy mở thực đơn Start->Programs->Development Kits->Windows DDK xxxx.xxxx->Build Environments->Windows XP->Windows XP Checked Build Environment (tùy theo hệ điều hành đang sử dụng mà các bạn có thể chọn trình biên dịch khác).Trong cửa sổ của trình biên dịch hãy gõ “cd sample1-1″ bấm enter rồi gõ “build” .

buildexample


- Để đưa được trình điều khiển thiết bị vào bộ nhớ có 2 cách là : cách chính thống (an toàn nhưng chậm và thiếu tính bảo mật ) và cách dơ (nguy hiểm nhưng nhanh và khó phát hiện).Sau đây là đọan mã viết bằng C theo cách chính thống:



/////////////////////////////////////////////////////////////////////////////////////////


int _cdecl main(void)

{

HANDLE hSCManager;

HANDLE hService;

SERVICE_STATUS ss;


hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);


printf(”Load Driver\n”);



if(hSCManager)

{

printf(”Create Service\n”);


hService = CreateService(hSCManager, “sample1-1″,

“Example Driver“,

SERVICE_START | DELETE | SERVICE_STOP,

SERVICE_KERNEL_DRIVER,

SERVICE_DEMAND_START,


SERVICE_ERROR_IGNORE,

“E:\\Program Files\\DDK\\sample1-1.sys”,

NULL, NULL, NULL, NULL, NULL);


if(!hService)

{

hService = OpenService(hSCManager, “sample1-1″,

SERVICE_START | DELETE | SERVICE_STOP);

}


if(hService)


{

printf(”Start Service\n”);


StartService(hService, 0, NULL);

printf(”Press Enter to close service\r\n”);

getchar();

ControlService(hService, SERVICE_CONTROL_STOP, &ss);


DeleteService(hService);


CloseServiceHandle(hService);



}


CloseServiceHandle(hSCManager);

}


return 0;

}


-Đó là cách chính thống . Còn cách bẩn thì tôi sẽ đề cập trong những bài sau.Để thuận tiện cho việc học tập các bạn có thể dùng chương trình để đưa trình điều khiển thiết bị vào bộ nhớ tại http://www.beyondlogic.org/dddtools/installer.zip . Như vậy là bạn đã có thể tạo ra một trình điều khiển thiết bị.

drvinst

////////////////////////////////////////////////////////////////////////////////////////


#include “ntddk.h”



NTSTATUS MyOpen(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )

{

//……..

return STATUS_SUCCESS;

}


NTSTATUS MyClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )

{

//……..

return STATUS_SUCCESS;


}


NTSTATUS MyRead(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )

{

//……..

return STATUS_SUCCESS;

}


NTSTATUS MyWrite(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )

{

//……..


return STATUS_SUCCESS;

}


NTSTATUS MyIoControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )

{

PIO_STACK_LOCATION IrpSp;

ULONG FunctionCode;

IrpSp = IoGetCurrentIrpStackLocation(Irp);

FunctionCode=IrpSp->Parameters.DeviceIoControl.IoControlCode;


switch (FunctionCode)//day la ma IRP cua chuong trinh gui len, tuy theo quy uoc truoc ma trinh dieu khien thiet bi se lam gi

{

// tat ca so o day phai la he 8

case 50721://day la so 020945 trong he 10

{

DbgPrint(”Happy Birthday to VietNam plz ! ^_^”);

}

case 1113716: // day la so 301006 trong he 10

{


DbgPrint(”Happy Birthday to HardSoft plz ! ^_^”);

}

case 774135: // day la so 260189 trong he 10

{

DbgPrint(”Happy Birthday to TheK plz ! ^_^”);

}

}

return STATUS_SUCCESS;

}



VOID OnUnload( IN PDRIVER_OBJECT DriverObject )

{

DbgPrint(”Goodbye cruel world !\n”);

}


NTSTATUS DriverEntry( IN PDRIVER_OBJECT theDriverObject,

IN PUNICODE_STRING theRegistryPath )

{

//in ra man hinh 1 dong chu. ban co dung DebugView cua sysInternals de xem dong chu nay

DbgPrint(”From Here We Rule ! VietNam Rule !”);


// chi dinh ham de tiep nhan viec ngung trinh dieu khien thiet bi

theDriverObject->DriverUnload = OnUnload;

// chi dinh ham de tiep nhan viec tao kenh IRP

theDriverObject->MajorFunction[IRP_MJ_CREATE] = MyOpen;

// chi dinh ham de tiep nhan viec ngung kenh IRP

theDriverObject->MajorFunction[IRP_MJ_CLOSE] = MyClose;

// chi dinh ham de tiep nhan viec doc kenh IRP


theDriverObject->MajorFunction[IRP_MJ_READ] = MyRead;

// chi dinh ham de tiep nhan viec ghi vao kenh IRP

theDriverObject->MajorFunction[IRP_MJ_WRITE] = MyWrite;

// chi dinh ham de tiep nhan viec ghi vao kenh IRP

theDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = MyIoControl;


return STATUS_SUCCESS;

}


/////////////////////////////////////////////////////////////////////////////////////////


- Như vậy là bạn đã tạo ra được hàm để tiếp nhận thông tin từ chương trình chính.Tuy nhiên để chương trình chính biết được cần phải gởi thông tin cho ai , bạn cần phải đăng ký tên thiết bị trong nhân. Sau đây là đọan mã :

////////////////////////////////////////////////////////////////////////////////////////

#include “ntddk.h”


PDEVICE_OBJECT deviceObject = NULL;


NTSTATUS MyOpen(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )

{

//……..

return STATUS_SUCCESS;


}


NTSTATUS MyClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )

{

//……..

return STATUS_SUCCESS;

}


NTSTATUS MyRead(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )

{

//……..


return STATUS_SUCCESS;

}


NTSTATUS MyWrite(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )

{

//……..

return STATUS_SUCCESS;

}


NTSTATUS MyIoControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )

{


PIO_STACK_LOCATION IrpSp;

ULONG FunctionCode;

IrpSp = IoGetCurrentIrpStackLocation(Irp);

FunctionCode=IrpSp->Parameters.DeviceIoControl.IoControlCode;

switch (FunctionCode)//day la ma IRP cua chuong trinh gui len, tuy theo quy uoc truoc ma trinh dieu khien thiet bi se lam gi

{

// tat ca so o day phai la he 8

case 50721://day la so 020945 trong he 10


{

DbgPrint(”Happy Birthday to VietNam plz ! ^_^”);

}

case 1113716: // day la so 301006 trong he 10

{

DbgPrint(”Happy Birthday to HardSoft plz ! ^_^”);

}

case 774135: // day la so 260189 trong he 10

{


DbgPrint(”Happy Birthday to TheK plz ! ^_^”);

}

}

return STATUS_SUCCESS;

}


VOID OnUnload( IN PDRIVER_OBJECT DriverObject )

{

DbgPrint(”Goodbye cruel world !\n”);

}



NTSTATUS DriverEntry( IN PDRIVER_OBJECT theDriverObject,

IN PUNICODE_STRING theRegistryPath )

{


const WCHAR deviceLinkBuffer[] = L”\\DosDevices\\Sample1-1″;

const WCHAR deviceNameBuffer[] = L”\\Device\\Sample1-1″;

NTSTATUS ntStatus;

UNICODE_STRING deviceNameUnicodeString;

UNICODE_STRING deviceLinkUnicodeString;

// Chuan bi bo nho cho ten cua trinh dieu khien.


RtlInitUnicodeString (&deviceNameUnicodeString,

deviceNameBuffer );

RtlInitUnicodeString (&deviceLinkUnicodeString,

deviceLinkBuffer );

// dang ky thiet bi


ntStatus = IoCreateDevice ( theDriverObject,

0,

&deviceNameUnicodeString,


FILE_DEVICE_NULL,

0,

TRUE,

&deviceObject );

if( NT_SUCCESS(ntStatus))

ntStatus = IoCreateSymbolicLink (&deviceLinkUnicodeString,

&deviceNameUnicodeString );


//in ra man hinh 1 dong chu. ban co dung DebugView cua sysInternals de xem dong chu nay


DbgPrint(”From Here We Rule ! VietNam Rule !”);

// chi dinh ham de tiep nhan viec ngung trinh dieu khien thiet bi

theDriverObject->DriverUnload = OnUnload;

// chi dinh ham de tiep nhan viec tao kenh IRP

theDriverObject->MajorFunction[IRP_MJ_CREATE] = MyOpen;

// chi dinh ham de tiep nhan viec ngung kenh IRP

theDriverObject->MajorFunction[IRP_MJ_CLOSE] = MyClose;


// chi dinh ham de tiep nhan viec doc kenh IRP

theDriverObject->MajorFunction[IRP_MJ_READ] = MyRead;

// chi dinh ham de tiep nhan viec ghi vao kenh IRP

theDriverObject->MajorFunction[IRP_MJ_WRITE] = MyWrite;

// chi dinh ham de tiep nhan viec ghi vao kenh IRP

theDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = MyIoControl;

return STATUS_SUCCESS;


}

////////////////////////////////////////////////////////////////////////////////////////

-Và sau đây là đọan mã của chương trình con được viết bằng C để liên lạc với trình điều khiển thiết bị.

////////////////////////////////////////////////////////////////////////////////////////

#include “windows.h”

#include “stdio.h”


int _cdecl main(void)

{

HANDLE hDevice; // tay cam cua thiet bi


DWORD dwReturn;

BOOL res;

DWORD *pdg=0;

hDevice = CreateFile(”\\\\.\\sample1-1″, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);

printf(”Open driver\n”);

if(hDevice)

{

printf(”Driver handle is %d\n”,hDevice);

printf(”Send 50721 to driver \n”);


getchar();

res=DeviceIoControl(hDevice, // thiet bi can lien lac

50721, // ma thuc thi

NULL, 0,

NULL, 0,// bien nhan tra loi

&dwReturn,

NULL);


if (res)printf(”Comunication succeeds\n”);


printf(”Send 1113716 to driver \n”);


getchar();

res=DeviceIoControl(hDevice, // thiet bi can lien lac

1113716, // ma thuc thi

NULL, 0,

NULL, 0,// bien nhan tra loi

&dwReturn,

NULL);

if (res)printf(”Comunication succeeds\n”);


printf(”Send 774135 to driver \n”);


getchar();

res=DeviceIoControl(hDevice, // thiet bi can lien lac

774135,// ma thuc thi

NULL, 0,

NULL, 0,// bien nhan tra loi

&dwReturn,

NULL);

if (res)printf(”Comunication succeeds\n”);

CloseHandle(hDevice);


}

return 0;

}

////////////////////////////////////////////////////////////////////////////////////

inactexmple.

Để có tòan bộ mã nguồn của bài các bạn hãy vào đây : http://www.freewebtown.com/khoalhp261/sample1-1.zip


Đang bởi : Trần Hữu Đăng Khoa