Playing with the debugger x64dbg, I noticed that my application uses multiple threads as shown below:


Among them, one thread is certainly used for the window, as the application is a window application.

The strange thing is that the EIP never changes.

However, moving the window or write in it must change the EIP right? As the thread responsible for the window must run continuously in order to prevent the window from freezing.

Can you explain why the EIP never changes? Is it related to x64dbg?

Thanks !

  • explain eip never changes eip will change if you step in ,step over etc or if you forcibly change it (x64dbg is similar to ollydbg in 32 bit to forcibly change eip in ollydbg you need to select an address right click and click new origin here i think x64dbg will have something similar to change eip ) is that what you are querying
    – blabb
    Jun 29, 2017 at 2:52
  • EIP will also change when the program is running. I can move the window, and write on it. EIP must change then...
    – Duke Nukem
    Jun 29, 2017 at 8:07
  • 1
    still not clear have you set any breakpoint and are you in broken state ? you talk about moving widow does that mean you have a debugger attached but the exe is is running freely ? if yes the debugger does not do anything and it is simply waiting for an event to occur it doesn't know what your exe is doing and doesnt know where eip is at the present nanosecond (you do understand that the msgloop might be executing trillions of times and updating a gui to reflect those changes is almost impossible dont you ? )
    – blabb
    Jun 29, 2017 at 9:49
  • "if yes the debugger does not do anything and it is simply waiting for an event to occur it doesn't know what your exe is doing" - Yes, you are right about it. It may be the problem. But also the GUI not refreshed because of the threads speed. Which one is correct?
    – Duke Nukem
    Jun 30, 2017 at 22:32
  • 1
    josh explained that for you in his edit eip and timing stats in x64dbg threads window are enumerated periodically (around 2 seconds per cycle) so it is not tied with a debug event these details can also be seen if you add more columns to taskmanager / process monitor by sysinternals etc too
    – blabb
    Jul 1, 2017 at 8:25

3 Answers 3


x64dbg's "Threads" page only refreshes once every two seconds, not nearly fast enough to see much going on in threads that are mostly blocked waiting (such as an application's message loop thread).

You can verify that the thread is getting time-sliced by watching the "User Time" column. Move your window around for several seconds, and you should cause enough application code to run to see the "User Time" increment.

Edit addressing @Duke Nukem's comment:

Active debuggers on Windows rely on an event system, so most of them just sit around and don't do anything until an exception, breakpoint, or user interaction happens. These debuggers (WinDbg, VS, etc) won't show any thread state or anything like that while the target is running (you only get that information when the target is broken into).

This is where the confusion is coming in for people not familiar with x64dbg. The x64dbg Threads tab isn't tied into the debugging events system, it is just a monitoring tool that periodically scans all the threads in the target (even while it is running) and grabs timing stats and also queries the thread's context in order to display the current instruction pointer.

  • This is the correct answer. When the debuggee is running it makes no sense to query thread states constantly. If you are really interested you can double click the thread you're interested in and use the "Goto -> Origin" option to force refresh the registers and navigate to the current EIP/RIP.
    – mrexodia
    Jun 29, 2017 at 22:28
  • Two solutions are exposed here: 1) blabb comment saying that the debugger does not do anything and it is simply waiting for an event to occur it doesn't know what the exe is doing. It may explain why we can't see the EIP changing. 2) the GUI can't be refreshed as threads are so fast. Which one is correct?
    – Duke Nukem
    Jun 30, 2017 at 22:31
  • 1
    @DukeNukem - edited my answer to provide more details / clarification.
    – josh poley
    Jun 30, 2017 at 22:53

You can't view all thread's context at the same time. You should switch interested thread. For example now i'll switch from thread 3 to thread 2.

In Windbg you can list all thread in current process with "~".


0  Id: 6c4.4c0 Suspend: 1 Teb: 7ffde000 Unfrozen
1  Id: 6c4.240 Suspend: 1 Teb: 7ffdd000 Unfrozen
2  Id: 6c4.9dc Suspend: 1 Teb: 7ffdc000 Unfrozen
3  Id: 6c4.728 Suspend: 1 Teb: 7ffdb000 Unfrozen
4  Id: 6c4.b1c Suspend: 1 Teb: 7ffda000 Unfrozen

Then you can use '>~[Thread number]s'


eax=00000001 ebx=00000001 ecx=773b73a8 edx=26aa5eee esi=00000002 edi=00288800
eip=77b470b4 esp=0132f9b8 ebp=0132fb18 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
77b470b4 c3              ret

Now you can trace execution of thread 2, set bp and etc.

  • This doesn't answer the question.
    – josh poley
    Jun 29, 2017 at 15:37

Each user thread has its own instruction pointer, as all registers are saved and reloaded with new data when a thread switch occurs. https://en.wikipedia.org/wiki/Thread_(computing)#User_threads You can confirm this on x64dbg by clicking "switch thread" on a new thread in the Threads tab and then viewing the new instruction pointer in the CPU tab.

So, if there is action on a particular thread that you don't believe you are seeing, it might be because you are not viewing the disassembly for the correct thread. This means that you need to know which thread is performing the action in advance.

In analyzing one program, I set breakpoints within the code of each thread displayed in the Threads window to see what would happen when I interacted with a pop-up window in the debuggee. Taking care that the inserted breakpoints were located immediately after each thread's instruction pointer, I found that I succeeded in freezing the debuggee's main window, necessitating a complete logout to recover. So far, though, I can't isolate the code launched by the pop-up window. Maybe I need a conditional breakpoint?

I tried setting up a trace while the debuggee was open, hoping to catch the action generated by the pop-up window, but x64dbg threw an error: "Failed to start trace!"

Any ideas?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.