Launched a process sample_Hello through WinDbg and observed
following events:
ModLoad: 00400000 0041c000
Sample_Hello.exe
ModLoad: 77980000 77b00000
ntdll.dll
ModLoad: 76b10000 76c20000
C:\Windows\syswow64\kernel32.dll
ModLoad: 76d20000 76d67000
C:\Windows\syswow64\KERNELBASE.dll
ModLoad: 67fd0000 680ce000
C:\Windows\WinSxS\x86_microsoft.vc80.debugcrt_1fc8b3b9a1e18e3b_8.0.50727.6195_none_e4a70117006762dd\MSVCP80D.dll
ModLoad: 670e0000 67201000
C:\Windows\WinSxS\x86_microsoft.vc80.debugcrt_1fc8b3b9a1e18e3b_8.0.50727.6195_none_e4a70117006762dd\MSVCR80D.dll
ModLoad: 77050000 770fc000
C:\Windows\syswow64\msvcrt.dll
(3c0.1324): Break
instruction exception - code 80000003 (first chance)
eax=00000000 ebx=00000000 ecx=fb480000 edx=0008e3c8 esi=fffffffe
edi=00000000
eip=77a20fab esp=0018fb08 ebp=0018fb34 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b
es=002b fs=0053 gs=002b efl=00000246
ntdll!LdrpDoDebuggerBreak+0x2c:
77a20fab cc int 3
Process launched but execution halted with a Break instruction
exception (please see highlighted line above). Why this happened?
This is due to the fact called “breaking into the debugger”. We will see this later. Now let’s see how
many threads are there in this state. I’m expecting 1 since my application is a
single threaded application.
So, I’ve executed the command ~* on windbg.
0:000> ~*
. 0 Id:
3c0.1324 Suspend: 1 Teb: 7efdd000 Unfrozen
Start: *** WARNING: Unable
to verify checksum for Sample_Hello.exe
Sample_Hello!ILT+145(_wmainCRTStartup) (00411096)
Priority: 0 Priority class: 32 Affinity: 3
Indeed I’ve a thread. Let’s see
the stack of the thread:
0:000> ~*kb
. 0 Id: 3c0.1324 Suspend: 1 Teb: 7efdd000
Unfrozen
ChildEBP RetAddr Args to
Child
0018fb34 77a01383
7efdd000 7efde000 77a8206c ntdll!LdrpDoDebuggerBreak+0x2c
0018fcb0 779c52d6
0018fd24 77980000 7b14b7c0 ntdll!LdrpInitializeProcess+0x12cc
0018fd00 779b9e79 0018fd24 77980000 00000000 ntdll!_LdrpInitialize+0x78
0018fd10 00000000 0018fd24 77980000 00000000
ntdll!LdrInitializeThunk+0x10
So, after initialize process call there is a DebuggerBreak call.
Now I’ve executed the ‘g’ (go) and debugee will start running. Lets’s
see:
Yes, Debugee is in running state:
Debuggee is running...
Since my program uses for user input to terminate so program is waiting
for input. It is going to help me to see the state of the process.
Again I’ve used debugger break point to halt the application and now
would like to see how many threads are there:
0:001> ~*
0 Id: 3c0.1324
Suspend: 1 Teb: 7efdd000 Unfrozen
Start:
Sample_Hello!ILT+145(_wmainCRTStartup) (00411096)
Priority: 0 Priority class: 32 Affinity: 3
. 1 Id:
3c0.14c4 Suspend: 1 Teb: 7efda000 Unfrozen
Start:
ntdll!DbgUiRemoteBreakin (77a1f85a)
Priority: 0 Priority class: 32 Affinity: 3
Now we’ve two threads but my application is a single threaded
application, so what’s the other thread?
Let’s see the stack:
0 Id: 3c0.1324 Suspend: 1 Teb: 7efdd000
Unfrozen
ChildEBP RetAddr Args to
Child
0018fa24 76bc7379 00000003 671f4aa0 00001000
kernel32!ReadConsoleInternal+0x15
0018faac 76b4f1b2 00000003 671f4aa0 00001000 kernel32!ReadConsoleA+0x40
0018faf4 67151b6a 00000003 671f4aa0 00001000 kernel32!ReadFileImplementation+0x75
0018fb88 671514c7 00000000 671f4aa0 00001000
MSVCR80D!_read_nolock+0x62a [f:\dd\vctools\crt_bld\self_x86\crt\src\read.c @
233]
0018fbd8 67177da1 00000000 671f4aa0 00001000 MSVCR80D!_read+0x217
[f:\dd\vctools\crt_bld\self_x86\crt\src\read.c @ 93]
0018fc00 67180a7b 671f1d08 489faa4c 0018ff30 MSVCR80D!_filbuf+0x111
[f:\dd\vctools\crt_bld\self_x86\crt\src\_filbuf.c @ 136]
0018fc54 67fe6b2e 671f1d08 0018fd3f 0018fd4c MSVCR80D!fgetc+0x24b
[f:\dd\vctools\crt_bld\self_x86\crt\src\fgetc.c @ 49]
0018fc64 67fe67c5 0018fd3f 671f1d08 489daae2
MSVCP80D!std::_Fgetc+0xe
[f:\dd\vctools\crt_bld\self_x86\crt\src\fstream @ 37]
0018fd4c 67fe66ce 0018fe58 680c4950 00000000
MSVCP80D!std::basic_filebuf
>::uflow+0xb5 [f:\dd\vctools\crt_bld\self_x86\crt\src\fstream @ 362]
0018fd64 67fe1018 00000000 680c4950 0018fdd0
MSVCP80D!std::basic_filebuf
>::underflow+0x4e [f:\dd\vctools\crt_bld\self_x86\crt\src\fstream @ 341]
0018fd74 67fe1cb2 489daa7e 0018ff30 0018fe58
MSVCP80D!std::basic_streambuf
>::sgetc+0x38 [f:\dd\vctools\crt_bld\self_x86\crt\src\streambuf @ 113]
0018fdd0 67fe0f57 00001300 489daa5e 0018fe2c
MSVCP80D!std::basic_istream
>::_Ipfx+0x102 [f:\dd\vctools\crt_bld\self_x86\crt\src\istream @ 113]
0018fdf0 68040f31 680c49a4 00000000 489da9e6
MSVCP80D!std::basic_istream
>::sentry::sentry+0x47 [f:\dd\vctools\crt_bld\self_x86\crt\src\istream @ 86]
0018fe48 004115e6 680c49a4 0018ff2b 00000000
MSVCP80D!std::operator>> >+0x41
[f:\dd\vctools\crt_bld\self_x86\crt\src\istream @ 997]
0018ff30 004125b6 00000001 007d4778 007d57f0 Sample_Hello!wmain+0x66
[f:\fordebugging\sample_hello\sample_hello\sample_hello.cpp @ 28]
0018ff80 004123fd 0018ff94 76b233aa 7efde000
Sample_Hello!__tmainCRTStartup+0x1a6
[f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 594]
0018ff88 76b233aa 7efde000 0018ffd4 779b9ef2
Sample_Hello!wmainCRTStartup+0xd [f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c
@ 414]
0018ff94 779b9ef2 7efde000 7b14b514 00000000
kernel32!BaseThreadInitThunk+0xe
0018ffd4 779b9ec5 00411096 7efde000 00000000
ntdll!__RtlUserThreadStart+0x70
0018ffec 00000000 00411096 7efde000 00000000 ntdll!_RtlUserThreadStart+0x1b
# 1 Id: 3c0.14c4 Suspend: 1 Teb: 7efda000
Unfrozen
ChildEBP RetAddr Args to
Child
0051ff58 77a1f896 7b5db548 00000000 00000000 ntdll!DbgBreakPoint
0051ff88 76b233aa
00000000 0051ffd4 779b9ef2 ntdll!DbgUiRemoteBreakin+0x3c
0051ff94 779b9ef2 00000000 7b5db514 00000000
kernel32!BaseThreadInitThunk+0xe
0051ffd4 779b9ec5 77a1f85a 00000000 00000000
ntdll!__RtlUserThreadStart+0x70
0051ffec 00000000 77a1f85a 00000000 00000000
ntdll!_RtlUserThreadStart+0x1b
Thread 0 stack is known to me but what’s the thread 1. Actually the
thread 1 is the debugger thread. This injects this (thread 1) thread to target
process as part of break in command. So
the call was:
0051ff88 76b233aa
00000000 0051ffd4 779b9ef2 ntdll!DbgUiRemoteBreakin+0x3c
Since thread 1 is the active thread (marked with ‘.’) and
ntdll!DbgBreakPoint is the last call in the stack, lets unassembled it:
0:001> uf ntdll!DbgBreakPoint
ntdll!DbgBreakPoint:
7799000c cc int 3
7799000d c3 ret
Got it; this calls INT 3 (Interrupt 3). Execution freezes here. So
we’ve used the term “breaking into the debugger” at the beginning. It says that
user mode debugger can interrupt at any point of time to freeze the target
process. In response to this interrupt,
OS raises a structured exception (Windows SEH) in the context of break-in
thread and as result, first chance exception occurred with exception code 80000003
(first chance).
Happy Debugging...
Comments