1. Trang chủ
  2. » Công Nghệ Thông Tin

Kỹ thuật lập trình hỗn hợp (miscellaneous programming techniques )

20 230 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 20
Dung lượng 369,44 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Nếu bạn đã thực hiện chế độ người dùng truy cập chương trình liên quan đến đăng ký, bạn có thể có thể đoán như thế nào để sử dụng các chức năng trong một driver.. Nếu bạn đang chạy trong

Trang 1

Kỹ thuật lập trình hỗn hợp (Miscellaneous Programming

Techniques )

Bởi:

Khoa CNTT ĐHSP KT Hưng Yên

Truy cập vào Registry

Windows XP và Windows 98/Me ghi lại cấu hình và các thông tin quan trọng trong một

cơ sở dữ liệu gọi là đăng ký WDM trình điều khiển có thể gọi các chức năng được liệt

kê trong bảng 3-10 để truy cập các đăng ký Nếu bạn đã thực hiện chế độ người dùng truy cập chương trình liên quan đến đăng ký, bạn có thể có thể đoán như thế nào để sử dụng các chức năng trong một driver Tôi được tìm thấy hạt nhân-chế độ hỗ trợ đầy đủ các chức năng khác nhau, tuy nhiên, tôi nghĩ rằng giá trị của nó mô tả cách nào bạn có thể sử dụng chúng

Trang 2

Trong phần này, tôi sẽ thảo luận, trong số những thứ khác, các gia đình của ZwXxx thói quen và RtlDeleteRegistryValue, mà cung cấp các chức năng cơ bản đăng ký rằng suffices cho hầu hết các trình điều khiển WDM

Mở ra một registry key

Trước khi bạn có thể interrogate giá trị trong việc đăng ký, bạn cần phải mở các khoá

có chứa chúng Bạn sử dụng vào ZwOpenKey mở một chìa khóa hiện tại ZwCreateKey bạn sử dụng để mở hoặc một trọng điểm hiện tại hoặc để tạo ra một khoá mới Hoặc chức năng cần thiết bạn đầu tiên khởi tạo một OBJECT_ATTRIBUTES cơ cấu với tên của chủ chốt và (có lẽ) các thông tin khác OBJECT_ATTRIBUTES các cấu trúc đã công bố sau đây:

typedef struct _OBJECT_ATTRIBUTES {

ULONG Length;

HANDLE RootDirectory;

Trang 3

PUNICODE_STRING ObjectName;

ULONG Attributes;

PVOID SecurityDescriptor;

PVOID SecurityQualityOfService;

} OBJECT_ATTRIBUTES;

Hơn là khởi tạo một dụ của cấu trúc này bằng tay, nó dễ để sử dụng InitializeObjectAttributes vĩ mô, mà tôi tin về bạn để hiển thị

Giả, ví dụ, rằng chúng tôi muốn mở các dịch vụ chủ chốt cho các driver của chúng tôi The I / O Trưởng đại diện cho chúng tôi tên của khoá này như là một tham số để DriverEntry Vì vậy, chúng tôi có thể viết mã như sau:

NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,

PUNICODE_STRING RegistryPath)

{

OBJECT_ATTRIBUTES oa;

InitializeObjectAttributes(&oa, RegistryPath, OBJ_KERNEL_HANDLE │

OBJ_CASE_INSENSITIVE, NULL, NULL);

HANDLE hkey;

status = ZwOpenKey(&hkey, KEY_READ, &oa);

if (NT_SUCCESS(status))

{

ZwClose(hkey);

}

}

Trang 4

1 Chúng tôi đang bắt đầu các đối tượng thuộc tính cơ cấu pathname đăng ký với chúng tôi bằng cách cung cấp cho các I / O Trưởng đại diện và bảo mật với một NULL descriptor ZwOpenKey sẽ bỏ qua các an ninh descriptor anyway-bạn có thể xác định thuộc tính bảo mật chỉ khi bạn tạo một chìa khóa cho lần đầu tiên

2 ZwOpenKey sẽ mở khoá cho đọc và lưu trữ các kết quả xử lý của chúng tôi trong hkey biến

3 ZwClose là một thói quen chung cho đóng một để xử lý một hạt nhân-chế độ đối tượng Đây, chúng tôi sử dụng nó để đóng trình xử lý chúng tôi đã đăng ký vào chìa khóa

Các OBJ_KERNEL_HANDLE cờ, hiển thị trong mẫu mã trước, là rất quan trọng cho các hệ thống tích hợp Nếu bạn đang chạy trong bối cảnh của một người dùng sợi khi bạn gọi ZwOpenKey, và nếu bạn không cung cấp này bit, cờ, các bạn sẽ có được xử lý

sẽ được sẵn sàng cho người sử dụng chế độ xử lý Nó thậm chí có thể xảy ra rằng người

sử dụng chế độ-mã sẽ đóng trình xử lý mới và mở ra một đối tượng, lại nhận được cùng một số giá trị All of a sudden, các cuộc gọi của bạn để đăng ký chức năng sẽ được giao

dịch với các sai loại xử lý Những cách khác để mở registry phím

Ngoài ra vào ZwOpenKey, Windows XP cung cấp hai chức năng cho các phím mở đăng ký

IoOpenDeviceRegistryKey cho phép bạn mở một trong những phím đặc biệt đăng ký liên kết với một đối tượng điện thoại:

HANDLE hkey;

Status = IoOpenDeviceRegistryKey(pdo, flag, access, &hkey);

nơi pdo là địa chỉ của các đối tượng vật lý điện thoại (PDO) ở dưới cùng của trình điều khiển đặc biệt của bạn stack, cờ là một chỉ cho các khoá đặc biệt mà bạn muốn mở (xem

B ng 3-11), và truy cập là một ví dụ như mặt nạ truy cập KEY_READ

Tôi sử dụng IoOpenDeviceRegistryKey với PLUGPLAY_REGKEY_DEVICE cờ rất thường xuyên trong các trình điều khiển của riêng tôi Trong Windows XP, chức năng

Trang 5

này sẽ mở ra những thiết bị subkey Các thông số của phần cứng, chìa khóa cho điện thoại Trong Windows 98/Me, nó sẽ mở ra phần cứng, chìa khóa riêng của mình Các phím được đúng nơi để lưu trữ tham số thông tin về phần cứng Tôi sẽ thảo luận này phím đầy đủ chi tiết trong Chương 15 trong kết nối với các cài đặt và phân phối một driver

IoOpenDeviceInterfaceRegistryKey sẽ mở ra các phím kết hợp với một dụ của một thiết

bị giao diện đăng ký:

HANDLE hkey;

status = IoOpenDeviceInterfaceRegistryKey(linkname, access,

&hkey);

nơi linkname là liên kết tượng trưng tên của đăng ký và truy cập vào giao diện truy cập

là một mặt nạ như KEY_READ

Bắt và cài đặt các giá trị

Thông thường, bạn mở một chìa khóa vì đăng ký mà bạn muốn, để lấy một giá trị từ cơ

sở dữ liệu Các chức năng cơ bản mà bạn sử dụng cho mục đích là ZwQueryValueKey

Ví dụ, để lấy lại giá trị trong imagePath bằng driver dịch vụ chủ chốt-Tôi thật sự không biết lý do tại sao bạn muốn biết này, nhưng đó không phải là bộ phận của tôi-bạn có thể

sử dụng các mã sau đây:

UNICODE_STRING valname;

RtlInitUnicodeString(&valname, L"ImagePath");

size = 0;

status = ZwQueryValueKey(hkey, &valname, KeyValuePartialInformation,

NULL, 0, &size);

if (status == STATUS_OBJECT_NAME_NOT_FOUND ││ size == 0)

<handle error>;

size = min(size, PAGE_SIZE);

PKEY_VALUE_PARTIAL_INFORMATION vpip =

Trang 6

PKEY_VALUE_PARTIAL_INFORMATION) ExAllocatePool(PagedPool, size);

if (!vpip)

<handle error>;

status = ZwQueryValueKey(hkey, &valname, KeyValuePartialInformation,

vpip, size, &size);

if (!NT_SUCCESS(status))

<handle error>;

<do something with vpip->Data>ExFreePool(vpip);

Đây, chúng tôi thực hiện hai cuộc gọi để ZwQueryValueKey Mục đích của cuộc gọi đầu tiên là để xác định bao nhiêu không gian, chúng tôi cần phải phân bổ cho các cơ cấu KEY_VALUE_PARTIAL_INFORMATION chúng tôi đang cố gắng để lấy Thứ hai, gọi truy thông tin Tôi còn lại kiểm tra các lỗi trong mã này fragment lỗi vì đã không làm việc trong thực tế ra con đường cho chúng tôi mong đợi Đặc biệt, tôi đoán rằng các bước đầu tiên để gọi ZwQueryValueKey sẽ trở lại STATUS_BUFFER_TOO_SMALL (kể từ khi tôi qua nó không-một chiều dài đệm) Nó không làm điều đó, mặc dù Quan trọng là STATUS_OBJECT_NAME_NOT_FOUND mã không thành công, cho thấy giá trị thực

sự không tồn tại Vì vậy, tôi kiểm tra cho rằng chỉ có giá trị Nếu có một số lỗi khác ngăn cản ZwQueryValueKey từ làm việc, các cuộc gọi thứ hai sẽ uncover nó

Cái được gọi là "một phần" thông tin trong cơ cấu bạn lấy bằng cách này chứa các giá trị của dữ liệu và một mô tả về một loạt các dữ liệu dạng:

typedef struct _KEY_VALUE_PARTIAL_INFORMATION {

ULONG TitleIndex;

ULONG Type;

ULONG DataLength;

UCHAR Data[1];

} KEY_VALUE_PARTIAL_INFORMATION,

*PKEY_VALUE_PARTIAL_INFORMATION;

Trang 7

Loại hình là một trong những loại dữ liệu đăng ký liệt kê trong bảng 3-12 (Các loại dữ liệu là có thể có nhưng không quan tâm đến trình điều khiển thiết bị.) DataLength là chiều dài của dữ liệu giá trị, và dữ liệu là dữ liệu riêng của mình TitleIndex không có liên quan đến trình điều khiển Dưới đây là một số dữ kiện hữu ích để biết về các loại

dữ liệu khác nhau:

• REG_DWORD là 32-bit unsigned integer ở định dạng nào (về cuối lớn hay nhỏ cuối)

là nền tảng cho tự nhiên

• REG_SZ mô tả một null-Unicode chấm dứt chuỗi giá trị The Terminator null được bao gồm trong DataLength truy cập

• Để mở rộng một REG_EXPAND_SZ có giá trị bằng cách thay biến môi trường, quý

vị nên RtlQueryRegistryValues như của bạn sử dụng phương pháp hỏi các đăng ký Nội

bộ cho các thói quen truy cập các biến môi trường không phải là tài liệu hoặc xúc cho

sử dụng bởi trình điều khiển

• RtlQueryRegistryValues cũng là một cách tốt để interrogate REG_MULTI_SZ giá trị trong đó nó sẽ gọi của bạn được xem thường gọi một lần cho mỗi phòng trong số có tiềm năng rất nhiều những dây

Chú thích:

Mặc dù, rõ ràng ích của RtlQuery ¬ RegistryValues, tôi đã được tránh bằng cách sử dụng nó bao giờ hết, vì nó sẽ gây ra vụ đụng xe trong một trong các trình điều khiển của tôi Tất nhiên, giá trị tôi đã đọc các chức năng cần thiết để gọi giúp đỡ một chức năng

đã được đặt trong sở khởi phần của hạt nhân và đã được, do đó, hiện nay không còn

Để thiết lập một giá trị đăng ký, bạn phải có KEY_SET_VALUE truy cập vào cha mẹ chìa khóa Tôi đã sử dụng KEY_READ sớm hơn, đó sẽ không cho bạn truy cập như

Trang 8

vậy Bạn có thể sử dụng KEY_WRITE hay KEY_ALL_ACCESS, mặc dù bạn thu được nhiều hơn do đó cần thiết cho phép Sau đó, gọi ZwSetValueKey Ví dụ:

RtlInitUnicodeString(&valname, L"TheAnswer");

ULONG value = 42;

ZwSetValueKey(hkey, &valname, 0, REG_DWORD, &value,

sizeof(value));

Subkeys xóa hoặc giá trị

Để xóa một giá trị trong một chìa khóa mở ra, bạn có thể sử dụng RtlDeleteRegistryValue trong cách đặc biệt sau đây:

RtlDeleteRegistryValue(RTL_REGISTRY_HANDLE, (PCWSTR) hkey,

L"TheAnswer");

RtlDeleteRegistryValue nói chung là một dịch vụ có chức năng đầu tiên đối số có thể chỉ định một trong một số nơi đặc biệt trong các đăng ký Khi bạn sử dụng RTL_REGISTRY_HANDLE, như tôi đã làm trong ví dụ này, bạn chỉ ra rằng bạn đã có một mở khoá để xử lý trong vòng mà bạn muốn xóa một giá trị Bạn chỉ rõ trọng điểm (với một ném biên để làm cho hạnh phúc) như là đối số thứ hai Thứ ba, và cuối cùng là đối số-null chấm dứt Unicode tên của giá trị mà bạn muốn xóa Đây là một trong những thời gian khi bạn không có để tạo ra một cơ cấu UNICODE_STRING để mô tả chuỗi

Trong Windows 2000 và sau này, bạn có thể sử dụng ZwDeleteValueKey để xóa một giá trị (nó là một giám sát rằng chức năng này không phải là tài liệu trong DDK):

UNICODE_STRING valname;

RtlInitUnicodeString(&valname, L"TheAnswer");

RtlDeleteValueKey(hkey, &valname);

Bạn có thể xoá chỉ những phím mà bạn đã mở ra với ít nhất là cho phép XOÁ (mà bạn nhận được với KEY_ALL_ACCESS) Gọi ZwDeleteKey bạn:

ZwDeleteKey(hkey);

Chìa khóa cho đến khi cuộc sống trên tất cả các xử lý đang đóng cửa, nhưng các nỗ lực

để mở một cửa hàng mới để xử lý các phím hoặc để truy cập vào các phím bằng cách sử

Trang 9

dụng bất cứ hiện đang mở xử lý sẽ không thành công với STATUS_KEY_DELETED.

Kể từ khi bạn có một mở xử lý tại điểm này, bạn cần phải chắc chắn sẽ được gọi ZwClose sometime (The DDK tài liệu hướng dẫn cho các mục nhập ZwDeleteKey nói những xử lý sẽ trở thành không hợp lệ It doesnt-bạn vẫn phải đóng nó bằng cách gọi điện thoại ZwClose.)

Enumerating Subkeys hoặc các giá trị

Một hoạt động phức tạp, bạn có thể thực hiện với một ký mở là chìa khóa để enumerate các yếu tố (subkeys và giá trị) mà có chứa chìa khóa Để làm được điều này, bạn sẽ thấy đầu tiên gọi ZwQueryKey để xác định một vài thực tế về các subkeys và các giá trị, chẳng hạn như số điện thoại của người, độ dài của tên lớn nhất, và như vậy trên ZwQueryKey có một đối số cho biết rằng đó của ba loại thông tin bạn muốn tải về các phím Các loại được đặt tên cơ bản, node, và đầy đủ Để chuẩn bị cho một Enumeration, bạn muốn được quan tâm đầu tiên trong đầy đủ thông tin:

typedef struct _KEY_FULL_INFORMATION {

LARGE_INTEGER LastWriteTime;

ULONG TitleIndex;

ULONG ClassOffset;

ULONG ClassLength;

ULONG SubKeys;

ULONG MaxNameLen;

ULONG MaxClassLen;

ULONG Values;

ULONG MaxValueNameLen;

ULONG MaxValueDataLen;

WCHAR Class[1];

} KEY_FULL_INFORMATION, *PKEY_FULL_INFORMATION;

Trang 10

Đây thực sự là cơ cấu của biến chiều dài từ Lớp [0] chỉ là những ký tự đầu tiên của tên lớp học It's phong tục để thực hiện một cuộc gọi để tìm hiểu cách thức lớn, một buffer bạn cần phải phân bổ và một cuộc gọi thứ hai để có được những dữ liệu, như sau: ULONG size;

ZwQueryKey(hkey, KeyFullInformation, NULL, 0, &size);

size = min(size, PAGE_SIZE);

PKEY_FULL_INFORMATION fip = (PKEY_FULL_INFORMATION)

ExAllocatePool(PagedPool, size);

ZwQueryKey(hkey, KeyFullInformation, fip, size, &size);

Bây giờ bạn đã được quan tâm trong subkeys đăng ky của bạn, bạn có thể thực hiện trong vòng lặp sau đây gọi ZwEnumerateKey:

for (ULONG i = 0; i < fip->SubKeys; ++i)

{

ZwEnumerateKey(hkey, i, KeyBasicInformation, NULL, 0, &size);

size = min(size, PAGE_SIZE);

PKEY_BASIC_INFORMATION bip = (PKEY_BASIC_INFORMATION)

ExAllocatePool(PagedPool, size);

ZwEnumerateKey(hkey, i, KeyBasicInformation, bip, size, &size);

<do something with bip->Name>

ExFreePool(bip);

}

Chìa khóa thực tế, bạn khám phá về mỗi subkey là tên của nó, mà cho thấy tính lên như

là một chuỗi Unicode trong cơ cấu KEY_BASIC_INFORMATION bạn lấy bên trong vòng lặp:

typedef struct _KEY_BASIC_INFORMATION {

Trang 11

LARGE_INTEGER LastWriteTime;

ULONG Type;

ULONG NameLength;

WCHAR Name[1];

} KEY_BASIC_INFORMATION, *PKEY_BASIC_INFORMATION

Không phải là tên null-chấm dứt, bạn phải sử dụng các NameLength thành thành viên

của các cơ cấu để xác định chiều dài của nó Đừng quên rằng trong chiều dài là byte!

Tên là không đầy đủ hoặc đường dẫn đăng ký; điều đó chỉ cần tên của subkey nào trong

vòng chìa khóa chứa nó Đây thật sự là may mắn, bởi vì bạn có thể dễ dàng mở một

subkey của nó cho một tên và xử lý để mở các bậc cha mẹ chìa khóa

Để một Enumeration của các giá trị trong một không gian mở chìa khóa, nhân viên của

các phương pháp sau đây:

ULONG maxlen = fip->MaxValueNameLen +

sizeof(KEY_VALUE_BASIC_INFORMATION);

maxlen = min(maxlen, PAGE_SIZE);

PKEY_VALUE_BASIC_INFORMATION vip = (PKEY_VALUE_BASIC_INFORMATION) ExAllocatePool(PagedPool, maxlen);

for (ULONG i = 0; i < fip->Values; ++i)

{

ZwEnumerateValueKey(hkey, i, KeyValueBasicInformation, vip,

maxlen, &size);

<do something with vip->Name>

}

ExFreePool(vip);

Trang 12

Cấp cho không gian lớn nhất có thể có cấu trúc

MaxValueNameLen dựa trên các thành viên của KEY_FULL_INFORMATION cơ cấu Bên trong vòng tròn, bạn sẽ thấy muốn làm cái gì với tên của giá trị, mà sẽ đến với bạn như là một chuỗi Unicode tính trong cấu trúc này:

typedef struct _KEY_VALUE_BASIC_INFORMATION {

ULONG TitleIndex;

ULONG Type;

ULONG NameLength;

WCHAR Name[1];

} KEY_VALUE_BASIC_INFORMATION, *PKEY_VALUE_BASIC_INFORMATION;

Một lần nữa, có tên của một giá trị và mở để xử lý các phụ huynh là chìa khóa chỉ cần những gì bạn cần để lấy lại giá trị, như được hiển thị trong phần trước

Hiện có các biến thể trên ZwQueryKey và trên hai Enumeration chức năng mà tôi đã không được thảo luận Bạn có thể, ví dụ, có được đầy đủ thông tin về một subkey khi bạn gọi ZwEnumerateKey Tôi chỉ cho bạn làm thế nào để có được những thông tin cơ bản bao gồm các tên Bạn có thể tải dữ liệu chỉ có giá trị, hoặc tên cộng với dữ liệu giá trị, từ ZwEnumerateValueKey Tôi chỉ cho bạn làm thế nào để có được tên của một giá trị

Truy cập tập tin

It's đôi khi hữu ích để có thể đọc và viết thường xuyên đĩa file từ bên trong một trình điều khiển WDM Có lẽ bạn cần phải tải về một số tiền lớn của microcode với phần cứng của bạn, hoặc có lẽ bạn cần phải tạo riêng của bạn rộng lớn của thông tin đăng nhập cho một số mục đích Có bộ ZwXxx thói quen để giúp bạn làm được những điều đó

Kích truy cập thông qua các thói quen ZwXxx yêu cầu bạn chạy được tại PAS ¬ SIVE_LEVEL (xem chương kế tiếp) trong một sợi mà có thể an toàn bị treo Trong thực tế, các yêu cầu sau có nghĩa là bạn phải không có khuyết tật Asynchronous Thủ tục cuộc gọi (APCs) bằng cách gọi điện thoại KeEnterCriticalRegion Bạn sẽ đọc trong chương kế tiếp rằng một số đồng bộ hóa primitives yêu cầu bạn đến IRQL nâng cao trên PASSIVE_LEVEL hay để vô hiệu hoá APCs Gấu chỉ cần ghi nhớ rằng những primitives và đồng bộ hóa tập tin không tương đang truy cập

Ngày đăng: 31/12/2015, 22:10

HÌNH ẢNH LIÊN QUAN

Hình 3-14. Driver Verifier thuật sĩ ban đầu trang - Kỹ thuật lập trình hỗn hợp (miscellaneous programming techniques )
Hình 3 14. Driver Verifier thuật sĩ ban đầu trang (Trang 16)
Hình 3-15. Driver Verifier thuật sĩ thứ hai trang - Kỹ thuật lập trình hỗn hợp (miscellaneous programming techniques )
Hình 3 15. Driver Verifier thuật sĩ thứ hai trang (Trang 17)
Hình 3-16. Driver Verifier của thuật sĩ cài đặt tuỳ chỉnh trang - Kỹ thuật lập trình hỗn hợp (miscellaneous programming techniques )
Hình 3 16. Driver Verifier của thuật sĩ cài đặt tuỳ chỉnh trang (Trang 18)
Hình 3-17. Điều khiển lựa chọn cho các trang Driver Verifier. Driver Verifier thất bại - Kỹ thuật lập trình hỗn hợp (miscellaneous programming techniques )
Hình 3 17. Điều khiển lựa chọn cho các trang Driver Verifier. Driver Verifier thất bại (Trang 20)

TỪ KHÓA LIÊN QUAN

w