# .thread, .thread2 (show the current thread and switch to another thread)

### Command

> .thread
>
> .thread2

### Syntax

> .thread
>
> .thread \[list] \[process Eprocess (hex)]
>
> .thread \[tid ThreadId (hex)]
>
> .thread \[thread Ethread (hex)]
>
> .thread2 \[tid ThreadId (hex)]
>
> .thread2 \[thread Ethread (hex)]

### Description

Shows or changes the current thread. These commands are logically designed to be used in [**Debugger Mode**](https://docs.hyperdbg.org/using-hyperdbg/prerequisites/operation-modes#debugger-mode). You can use the '[.attach](https://docs.hyperdbg.org/commands/meta-commands/.attach)' and the '[.detach](https://docs.hyperdbg.org/commands/meta-commands/.detach)' commands in [**VMI Mode**](https://docs.hyperdbg.org/using-hyperdbg/prerequisites/operation-modes#vmi-mode). However, you can use it to view the list of the threads in both [**VMI Mode**](https://docs.hyperdbg.org/using-hyperdbg/prerequisites/operation-modes#vmi-mode) and [**Debugger Mode**](https://docs.hyperdbg.org/using-hyperdbg/prerequisites/operation-modes#debugger-mode).

{% hint style="danger" %}
**Important:** the implementation of these commands is different. Please visit [**this article**](https://docs.hyperdbg.org/tips-and-tricks/considerations/difference-between-process-and-thread-switching-commands) to be aware of the differences and to know when you should use the '**.thread**' command and when you should use the alternative '.**thread2**' command.
{% endhint %}

If you want to change the thread to a new thread, after using the '**.thread**' or the '**.thread2**' commands, you should use the '[g](https://docs.hyperdbg.org/commands/debugging-commands/g)' command.

### Parameters

**\[list]**

It shows the list of threads.

**\[process Eprocess (hex)] (optional)**

If you specify the list as the first argument, you can optionally specify the target process that you want to see its threads, otherwise, the threads for the current process are shown.

**\[tid ThreadId (hex)]**

The thread id of the thread that you want to switch to it.

**\[thread Ethread (hex)]**

The `_ETHREAD` of the thread that you want to switch to it.

{% hint style="success" %}
If you don't specify any parameters to the '**.thread**' or the '**.thread2**' commands, it shows the threads of the current process.
{% endhint %}

### Examples

Use the following command to see the currently executing thread (and other information like thread and process object addresses and the image name).

```
3: kHyperDbg> .thread
thread id: e80 (pid: 40c)
thread (_ETHREAD): ffff948c`ba35a080
process (_EPROCESS): ffff948c`c1594340
process name (16-Byte): hyperdbg-cli.e
```

If you want to switch to a thread with a thread id equal to **23f8**, use the below command. After that, use the '[g](https://docs.hyperdbg.org/commands/debugging-commands/g)' command, and when the debuggee breaks again, you can see that the thread is changed to your requested thread.

```
2: kHyperDbg> .thread tid 23f8
press 'g' to continue the debuggee, if the tid or the thread object address is valid then the debuggee will be automatically paused when it attached to the target thread

2: kHyperDbg> g
debuggee is running...
switched to the specified thread
fffff801`63265c52    0F B6 87 84 01 00 00                movzx eax, byte ptr ds:[rdi+0x184]

3: kHyperDbg> .thread
thread id: 23f8 (pid: 1b6c)
thread (_ETHREAD): ffff948c`c1957080
process (_EPROCESS): ffff948c`c0a0d080
process name (16-Byte): test.exe
```

If you want to switch to a thread by using its thread object address (`nt!_ETHREAD`), use the following command.

```
2: kHyperDbg> .thread thread ffff948c`c1957080
press 'g' to continue the debuggee, if the tid or the thread object address is valid then the debuggee will be automatically paused when it attached to the target thread

2: kHyperDbg> g
debuggee is running...
switched to the specified thread
00007ff6`e8df2450    90                                  nop
```

If you want to see a list of threads in the **current process**.

```
2: kHyperDbg> .thread list
PROCESS ffff948cc1594340        IMAGE   hyperdbg-cli.e
        THREAD  ffff948cba186080 (40c.20c8)
        THREAD  ffff948cbfc7b080 (40c.1794)
        THREAD  ffff948cba35a080 (40c.e80)
```

If you want to view a list of threads of a special process, use its process object (`nt!_EPROCESS`) address. You can get a list of process objects list using the '[.process](https://docs.hyperdbg.org/commands/meta-commands/.process)' command.

```
2: kHyperDbg> .thread list process ffff948cc1590340
PROCESS ffff948cc1590340        IMAGE   MicrosoftEdgeU
        THREAD  ffff948cbf8f2080 (e08.1918)
        THREAD  ffff948cc056c080 (e08.c88)
        THREAD  ffff948cbfedf040 (e08.628)
        THREAD  ffff948cbf3ad080 (e08.18c0)
        THREAD  ffff948cc09ed080 (e08.1b00)
        THREAD  ffff948cc14ea080 (e08.888)
```

### IOCTL

This command works over serial by sending the serial packets to the remote computer.

First of all, you should fill the `DEBUGGEE_DETAILS_AND_SWITCH_THREAD_PACKET` structure.

Set the `ThreadId` or `Thread` to your target thread (if you want to change the current thread), set the `ActionType` to `DEBUGGEE_DETAILS_AND_SWITCH_THREAD_PERFORM_SWITCH` and leave the `Result`.

This is the enum for action type.

```clike
typedef enum _DEBUGGEE_DETAILS_AND_SWITCH_THREAD_TYPE
{

    DEBUGGEE_DETAILS_AND_SWITCH_THREAD_PERFORM_SWITCH,
    DEBUGGEE_DETAILS_AND_SWITCH_THREAD_GET_THREAD_DETAILS,
    DEBUGGEE_DETAILS_AND_SWITCH_THREAD_GET_THREAD_LIST,

} DEBUGGEE_DETAILS_AND_SWITCH_THREAD_TYPE;
```

If you want to get the current thread id and `_ETHREAD`, then set the `ActionType` to `DEBUGGEE_DETAILS_AND_SWITCH_THREAD_GET_THREAD_DETAILS` and leave the `ThreadId` and `Thread`.

If you want to see the list of threads, you should set the `ActionType` to `DEBUGGEE_DETAILS_AND_SWITCH_THREAD_GET_THREAD_LIST` and also fill the below structure with offsets derived from the PDB file in addition to the target process that you want to see its threads.

If you set `Process` to `NULL`, it shows the current process's threads.

```clike
typedef struct _DEBUGGEE_THREAD_LIST_NEEDED_DETAILS
{
    UINT32 ThreadListHeadOffset;     // nt!_EPROCESS.ThreadListHead
    UINT32 ThreadListEntryOffset;    // nt!_ETHREAD.ThreadListEntry
    UINT32 CidOffset;                // nt!_ETHREAD.Cid
    UINT64 PsActiveProcessHead;      // nt!PsActiveProcessHead
    ULONG  ActiveProcessLinksOffset; // nt!_EPROCESS.ActiveProcessLinks
    UINT64 Process;

} DEBUGGEE_THREAD_LIST_NEEDED_DETAILS, *PDEBUGGEE_THREAD_LIST_NEEDED_DETAILS;cccc
```

When you set `CheckByClockInterrupt` to `TRUE`, the semantics for the '**.thread**' is used and if you set it to `FALSE` then the '**.thread2**''s semantic is used for the **thread switch** request.

```c
typedef struct _DEBUGGEE_DETAILS_AND_SWITCH_THREAD_PACKET
{
    DEBUGGEE_DETAILS_AND_SWITCH_THREAD_TYPE ActionType;
    UINT32                                  ThreadId;
    UINT32                                  ProcessId;
    UINT64                                  Thread;
    UINT64                                  Process;
    BOOLEAN                                 CheckByClockInterrupt;
    UCHAR                                   ProcessName[16];
    DEBUGGEE_THREAD_LIST_NEEDED_DETAILS     ThreadListSymDetails;
    UINT32                                  Result;

} DEBUGGEE_DETAILS_AND_SWITCH_THREAD_PACKET, *PDEBUGGEE_DETAILS_AND_SWITCH_THREAD_PACKET;
```

After that, send the above structure to the debuggee when debuggee is paused and waiting for new command on **vmx-root** mode.

You should send the above structure with `DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_MODE_CHANGE_THREAD` as `RequestedAction` and `DEBUGGER_REMOTE_PACKET_TYPE_DEBUGGER_TO_DEBUGGEE_EXECUTE_ON_VMX_ROOT` as `PacketType`.

In return, the debuggee sends the above structure with the following type.

```c
DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_RESULT_OF_CHANGING_THREAD
```

In the returned structure, the `Result` is filled by the kernel.

If the `Result` is `DEBUGEER_OPERATION_WAS_SUCCESSFULL`, the operation was successful, and you should use the '[g](https://docs.hyperdbg.org/commands/debugging-commands/g)' command to move to the new thread. Otherwise, the returned result is an error, and the current thread is not changed. If you want the current thread, then if the `Result` is `DEBUGEER_OPERATION_WAS_SUCCESSFULL`, then the current thread id is stored at `ThreadId` and the thread object address is stored at `Thread`.

The following function is responsible for changing the core in the debugger.

```clike
BOOLEAN
KdSendSwitchThreadPacketToDebuggee(DEBUGGEE_DETAILS_AND_SWITCH_THREAD_TYPE ActionType,
                                   UINT32                                  NewTid,
                                   UINT64                                  NewThread,
                                   BOOLEAN                                 CheckByClockInterrupt,
                                   PDEBUGGEE_THREAD_LIST_NEEDED_DETAILS    SymDetailsForThreadList);
```

### Remarks

If you want to see a list of threads, you need to load the public symbol file (PDB) for the ntoskrnl.exe using the '[.sym](https://docs.hyperdbg.org/commands/meta-commands/.sym)' command.

The difference between these commands (**.thread** and **.thread2**) is explained [here](https://docs.hyperdbg.org/tips-and-tricks/considerations/difference-between-process-and-thread-switching-commands).

If you've entered an invalid address as `_ETHREAD` or an invalid thread id, HyperDbg keeps checking for the target address or TID, and whenever the debugger is paused again, it won't check for the thread anymore.

It also means that if you press the '[g](https://docs.hyperdbg.org/commands/debugging-commands/g)' command and an event or a breakpoint is triggered before switching to the new thread, switching will be ignored, and you need to re-switch to the target thread and use the '**.thread**' or '**.thread2**' commands again.

Some threads might never trigger even if their thread id or `ETHREAD` is valid. It is because in these cases, Windows halts or suspends those processes (and, of course, its threads) and never switches to them. In these cases, you can switch to the memory layout of the target process by changing **cr3** to your target **cr3**. For more details, please visit [here](https://docs.hyperdbg.org/tips-and-tricks/misc/switch-to-new-process-layout).

### Requirements

None

### Related

[.process, .process2 (show the current process and switch to another process)](https://docs.hyperdbg.org/commands/meta-commands/.process)

[Switching to a Specific Process or Thread](https://docs.hyperdbg.org/using-hyperdbg/user-mode-debugging/examples/basics/switching-to-a-specific-process-or-thread)

[Difference between process and thread switching commands](https://docs.hyperdbg.org/tips-and-tricks/considerations/difference-between-process-and-thread-switching-commands)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.hyperdbg.org/commands/meta-commands/.thread.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
