KD extension DLLs & kdcom Protocol

Source: Internet
Author: User
Tags sorted by name
KD extension DLLs & kdcom Protocol

Windbg debugger allows you to debug all modern versions of Windows using
Built-in kernel debugger and either com or ieee1394 port. Let's see how is it
Implemented. To start Windows in kernel debugging mode, you specify additional
Parameters inBoot. ini
File that look like this:

Multi (0) disk (0) RDISK (0) Partition (1)/Windows = "Microsoft
Windows XP Professional "/noexecute = optin/fastdetect/debug
/Debugport = 1394

Let's now see what actually happens when ntoskrnl detects that it was started
With/Debug
Parameter. First of all, it analyzes/Debugport
Parameter fromBoot. ini
And determines what packet-level plugin (KD
Extension DLL

In Microsoft terminology) to load. For com-based debugging
Plugin DLL is called kdcom. dll, for IEEE1394-based debugging it is called
Kd1394.dll. Fortunately, when you specify something like/Debugport = foo
,
Ntoskrnl will try to load kdfoo. dll and use it as a KD extension DLL. As we are
Providing our own DLL making a fast interface to windbg, that expects a named
Pipe from a virtual COM port, we need to solve two problems here:

  • The problem of creating a valid KD extension DLL, I. e. Providing
    Same set of exported functions working in an expected way.
  • The problem of understanding and reimplementing kdcom protocol, I. e.
    Providing the same data at the end of our fast pipe, as the original
    Kdcom. dll provides.

Note that in Windows Vista the kernel debugging flags are specified using
Bcdedit.exe

Utility and cannot specify a non-standard KD extension DLL.
Only way to load kdvmware DLL to kernel is to replace a standard one,
Example, kd1394.dll.

KD extension DLLs

Let's just e the structure of a typical KD extension DLL. A quick
Analysis of kdcom. dll shows that it exports the following functions:

Exports from kdcom. dll
8 exported name (s), 8 Export addresse (s). ordinal base is 1.
Sorted by name:
RVA Ord. Hint name
--------------------
00000386 1 0000 kdd0transition
00000386 2 0001 kdd3transition
000003a6 3 0002 kddebuggerinitialize0
0000044c 4 0003 kddebuggerinitialize1
00000f4c 5 0004 kdreceivepacket
00000460 6 0005 kdrestore
00000456 7 0006 kdsave
201711b2 8 0007 kdsendpacket

Let's analyze how this functions work.

Initialization

As it is evident from their names, two functions are used to initialize a KD
Extension DLL: kddebuggerinitialize0 ()
And
Kddebuggerinitialize1 ()
. Fortunately, Microsoft
Provides PDB file for WINXP version of kdcom. dll. Additionally, some of
Functions are described by Ken Johnson (http://www.nynaeve.net /? P = 169
). Let's use
The PDB to recover
Declarations for the initialization functions:

Ntstatus ntapi kddebuggerinitialize0 (ploader_parameter_block

Lploaderparameterblock );
Ntstatus ntapi kddebuggerinitialize1 (ploader_parameter_block

Lploaderparameterblock );

The first function performs initialization of a KD extension DLL.
Example, it can read the parameters specified in Boot. ini using


Loader_parameter_block
: Loadoptions
Field. For example, kdcom. dll can
Get determine the COM port number to use and its baud rate. Both Initialization
Functions return a ntstatus
Value
STATUS_SUCCESS
Corresponding to successful
Completion. Note that if an initialization function such
Kddebuggerinitialize0 ()
Returns an unsuccessful
Status, kernel is started without debugging support and the DLL is not actually
Used any more.

Sending and processing ing packets

All communication between kernel and a kernel debugger is packet-based.
Following Rules describe the packet behavior:

  • All KD extension DLL cballs are called synchronously, I. e. shocould not
    Leave any executing code after they return.
  • A kd extension DLL guarantees successful packet delivery, I. e. retries
    Sending a packet when kdsendpacket ()
    Was
    Called until debugger acknowledges it.
  • Kernel uses polling model to check whether new packets are available.
    For that purpose it CILS kdreceivepacket ()

    With a special parameter.

  • When kernel wants to receive a packet, it knows the type of the packet
    To receive. It passes this type to kdreceivepacket ()

    That drops all packets of other types (and sends corresponding resend
    Requests ).

  • Each send/receive operation uses 2 buffers for data transfer. Typically,
    The first buffer contains some fixed-size message header and the second one
    Contains variable-sized message body. However, this is a typical use case,
    Not the only one. Basically, in a send operation the two buffers are simply
    Sent one after another as a single data block with no additional indication
    Where the first one ends and the second one starts. When a receive Function
    Is called with first buffer having a size of n Bytes, the first n Bytes
    The message is put to it, while the rest is put to the second buffer.

Each buffer is represented by a string

Structure defined inNtdef. h
(On x64 systems the data
Pointer is aligned at 8-byte boundary ):

Typedef struct
_ String {
Ushort length;
Ushort maximumlength;
Pchar buffer;
} String, * pkd_buffer;

In kdvmware this structure is redefined as kd_buffer
.

A special structure called kd_context

Maintains the global state for KD packet layer:

Typedef struct
_ Kd_context
{
Ulong retrycount;
Boolean breakinrequested;
} Kd_context, * pkd_context;
 

The retrycount
Member is set before a call
Kdsendpacket ()
And specifies the number
Retries for a droppable packet to set. A droppable packet is a packet that can
Be simply dropped if no acknowledgment comes from windbg after some number
Retries (kdsendpacket ()
Will just return).
Breakinrequested
Is set
True
By kdreceivepacket ()
If windbg has requested a kernel breakpoint (CTRL + break was
Pressed, or windbg was just started). The break-in request is not a part of
Packet and is transferred separately (see kdcom protocol description below ).

Here are the definitions for packet sending and processing ing functions:

Void
Ntapi kdsendpacket (_ in

Ulong packettype,

_ In
Pkd_buffer firstbuffer,

_ In_opt
Pkd_buffer secondbuffer,

_ Inout
Pkd_context kdcontext );

Kd_recv_code
Ntapi kdreceivepacket (_ in
Ulong packettype,

_ Inout_opt
Pkd_buffer firstbuffer,

_ Inout_opt
Pkd_buffer secondbuffer,

_ Out_opt
Pulong payloadbytes,

_ Inout_opt
Pkd_context kdcontext );

The kdreceivepacket ()
Return value can be
Defined as a following enumeration:

Typedef Enum
_ Kd_recv_code
{
Kd_recv_code_ OK = 0,
Kd_recv_code_timeout = 1,
Kd_recv_code_failed = 2
} Kd_recv_code, * pkd_recv_code;

The packettype
Parameter specifies the type
Of the packet being sent or being stored ed (all packets with other types shound
Be ignored), however there is one exception. When
Packettype
Is set to 8 in a kdreceivepacket ()

Call, the function checks whether there is any data available (for example,
Whether the COM port buffer is non-empty), and returnsImmediately
Either kd_recv_code_ OK
Or
Kd_recv_code_timeout
.

Additional support functions

A kd extension DLL exports some additional functions that are not directly
Involved in packet sending/inserting ing and can simply return
STATUS_SUCCESS
In most of implementations:

Ntstatus ntapi kdd0transition ();
// Called when the debug port device shoshould be powered
On

Ntstatus ntapi kdd3transition ();
// Called when the debug port device shoshould be powered
Off

Ntstatus ntapi kdsave (bool sleeptransaction );
// Saves the debug port State before standby or
Hibernation

Ntstatus ntapi kdrestore (bool sleeptransaction );
// Restores originally saved debug port State

The information about these functions was taken from
Rectos documentation
Pages
. Although Microsoft implementation can be different from reactos one,
Just returning STATUS_SUCCESS
From these
Functions shoshould work.

Kdcom Protocol

Another problem to be solved in order to connect kernel and windbg using
Custom KD extension DLL is the protocol that kdcom. dll uses to transfer packets
Over a COM port. As windbg between ES and sends kdcom packets when connected to
Kernel using a named pipe, our tool shocould be able to produce and to parse such
Packets. In kdvmware these packets are processed in kdclient. dll on host
Side, however, in Microsoft implementation, all packet processing logic is
Implemented inside kdcom. dll. Let's see, how it works.

First of all, there are two kinds of packets: control packets and Data
Packets. data packets directly transfer kdsendpacket ()/kdreceivepacket ()

Data, while control packets signalize receive acknowledgment, retry requests,
Resync requests, etc. Each control packet consists of a packet header, a data
Block, and a terminating byte (0xaa
). A data
Block contains contents of two buffers, one after another, with no indication
Where one ends and another starts. Moreover, sender and receiver er can use split
The packet data in different ways:

Let's define a C structure describing the packet header:

Typedef struct
_ Kd_packet_header
{
Ulong signature;
Ushort packettype;
Ushort totaldatalength;
Ulong packetid;
Ulong checksum;
} Kd_packet_header, * pkd_packet_header;

Packet Signature
Is either 0x30303030
('20140901'

)
For data packets, or 0x69696969
For control
Packets ('iii'

).
Packet type
Specifies the exact type of the packet. types for Control and Data
Packets are members of the same enumeration:

Enum

{
Kdpackettype3 = 3,
Kdpacketacknowledge = 4,
Kdpacketretryrequest = 5,
Kdpacketresynchronize = 6,
Kdpackettype7 = 7,
Kdcheckforanypacket = 8,
Kdpackettype11 = 11,
};

As it was described before, packet type 8 is not used as a packet type.
Instead, when kdreceivepacket ()
Is called
That value, it checks whether any data can be partitioned ed from windbg and returns
Immediately.

Packet ID
Is used to detect if a single packet was missed, as the least
Significant Bit Of A packet ID toggles with every new packet sent. The initial
Packet ID is 0x80800800
, However, resync command
Sets it to 0x80800000
.Checksum
Is just
An Arithmetic sum of all bytes from the data section of the packet.

As I have discovered after development of kdvmware, a file named
Windbgkd. h

Was authorized ded in Windows 2000 DDK and contained information about
Kdcom protocol internals. The reactos version containing most of the information
From it can be found

Here
. According to that file, the following packet types are actually
Used:

# Define
Packet_type_unused 0
# Define
Packet_type_kd_state_change32 1
# Define
Packet_type_kd_state_manipulate 2
# Define
Packet_type_kd_debug_io 3
# Define
Packet_type_kd_acknowledge 4
# Define
Packet_type_kd_resend 5
# Define
Packet_type_kd_reset 6
# Define
Packet_type_kd_state_change64 7
# Define
Packet_type_kd_poll_breakin 8
# Define
Packet_type_kd_trace_io 9
# Define
Packet_type_kd_control_request 10
# Define
Packet_type_kd_file_io 11
# Define
Packet_type_max 12

Let's discuss the types of control packets and their roles in kdcom protocol:

  • Acknowledgment packets are sent by both kernel and windbg when a data
    Packet was successfully received.
  • Resend packet is sent when kernel or windbg has initialized ed a damaged
    Packet, a packet with wrong id, or a packet with unexpected type.
  • Resync packet is sent by windbg when it is initially connected
    Kernel. The kernel acknowledges Resync operation by sending back another
    Resync packet.

To initialize strate, how kdcom packet layer works, let's check out some examples:

  1. Normal operation. kernel continiously checks for new packets. When
    Packet is found, kernel es it (assuming it knows the type for
    Packet ).
  2. Normal packet sending. kernel sends a packet to windbg.
    Kdsendpacket ()
    Waits for acknowledgment
    Packet from windbg.
  3. Packet sending with retry. kernel sends a packet to windbg, however
    Latter does not receive it. kdcom then resends the packet after timeout.
  4. Packet collision. kernel sends a packet to windbg when windbg sends
    Packet to kernel. kernel sends a Resend Request to windbg. The latter gets
    The data packet instead of acknowledgment and buffers it. Then acknowledges
    It, es a Resend Request for the first packet and sends it once again.
    Kdcom events es acknowledgement and returns control to kernel, that cballs
    Kdreceivepacket ()
    To get packet from windbg
    (If expects one ).
  5. Resynchronization. kernel events es a packet
    And encounters a Resync request from windbg.
Droppable packets

Some packets are "droppable". It means that
Kdsendpacket ()
May return control when such a packet was not acknowledged
By windbg after some number of retries. kdcom. dll treats the following packets
As droppable:

  • Type 3, subtype 0x3230
  • Type 7, subtype 0x3031
  • Type 11, subtype 0x3430

Packet subtype (apinumber) is the first DWORD in the packet data block.
Types referenced here is defined in the following way inWindbgkd. h
:

# Define
Dbgkdprintstringapi
Zero X 00003230
# Define
Dbgkdloadsymbolsstatechange 0x00003031resync bounce Problem

There is one significant detail in original kdcom implementation. When
Kdcom. dll initializes, it reinitializes the COM port and resets its buffer.
Named Pipe implementation shocould do the same. In other case, the following
Scenario is possible:

  1. Windbg connects to a named pipe with no kernel listening and sends a few
    Resync packets.
  2. Kernel loads our kd dll, it has es first Resync packet and replies
    With a resync.
  3. Windbg resynchronizes and sends some data.
  4. Kernel slaves es another Resync from buffer and resyncs again, replying
    With a resync.
  5. Windbg receives an unexpected Resync, resynchronizes and sends another
    Resync packet to acknowledge resynchronization.
  6. The windbg/kernel couple will continue producing Resync packets till
    End of time and will never synchronize normally.

To avoid this problem, kdvmware simply clears the named pipe Receive Buffer
When it comes to es a Resync packet.

Implementation in kdvmware

All kdcom-related functionality is implemented in
Kdcomdispatcher

Class. Feel free to release e its documentation using the link abve.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.