Pending breakpoint in windbg - debugging

Remote debugging is not possible & need to debug my code for an issue not reproducible on my system.
I can set a pending breakpoint in gdb on linux. I need something similar on windbg or on windows platform as I cannot share the source file but I need to break in the file at particular line in order to debug.

what do you mean by pending breakpoint ?
does the module in which the function resides loaded dynamically and you need to set a breakpoint beforehand ?
if yes then use bu breakpoints
bu myfoomodule!myblahfunction
this will load the symbols when the module is loaded and set a breakpoint as and when needed
0:000> lm m help*
Browse full module list
start end module name
<<<<<<<<<<<< no results here
lets confirm by forcefully realoding symbols and checking for the existence of
this module
0:000> .reload /f
Reloading current modules
0:000> lm m help*
Browse full module list
start end module name
again no results we cant set a regular breakpoint
our breakpoint needs to be set using unresolved breakpoint
lets set it
0:000> bu HelpPaneProxy!DllMain
let us check
0:000> bl
0 e Disable Clear u 0001 (0001) (HelpPaneProxy!DllMain)
lets continue
0:000> g
ModLoad: 77ac0000 77adf000 C:\Windows\system32\IMM32.DLL
ModLoad: 76f90000 7705c000 C:\Windows\system32\MSCTF.dll
un needed mod load display cut off XXXXXXXXXXXXXXXXXXXX
ModLoad: 67d80000 67d91000 C:\Windows\System32\HelpPaneProxy.dll
bingo our breakpoint hit on the module load triggered after clicking help in calc
Breakpoint 0 hit
eax=00000001 ebx=00000001 ecx=00000001 edx=00000000 esi=00000000 edi=0025cfa8
eip=67d84700 esp=0025ce7c ebp=0025ced8 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
HelpPaneProxy!DllMain:
67d84700 8bff mov edi,edi

Related

How to debug a windows driver with IDA and use its corresponding IDB?

I am familiar with using windbg or IDA for remote kernel debugging, but right now i have extracted a kernel driver from an executable, and have done static analysis on its IDB and renamed a lot of variables, what is the easiest way of using my IDB file to debug the driver on the remote debugee when it gets loaded by the executable?
I know how to attach to remote kernel using IDA, but how can i use my current IDB file, and put breakpoint on some of its functions so it they get hit when the driver is loaded? (I dont have the corresponding pdb file for the driver so i can't use symbols for breakpoint)
this is a vanilla windbg answer to break on any DriverInit
once you have Broken on DriverInit You Can Lookup and Set bp on all MajorFunctions
Assuming you have a regular kd Connection
use sxe -ibp;.reboot to reboot the target
on reconnection the target will break very Early as below
kd> sxe ibp;.reboot
Shutdown occurred at (Sun Oct 18 02:58:09.077 2020 )...unloading all symbol tables.
Waiting to reconnect...
Connected to Windows 7 7601 x86 compatible target at (xxx), ptr64 FALSE
Kernel Debugger connection established. (Initial Breakpoint requested)
once broken set a breakpoint on nt!IopLoadDriver
inside this function search for an indirect Call
that Calls the _DRIVER_OBJECT->DriverInit
kd> ?? #FIELD_OFFSET(nt!_DRIVER_OBJECT , DriverInit)
long 0x2c
like
nt!IopLoadDriver+0x7ea:
829d5355 ff562c call dword ptr[esi+2Ch] ds:84f2928c={cdrom!FxDriverEntry (87eb53cf)}
set a break point here to
you are now set to enter almost every driver that is loaded
once you are on entrypoint of any Driver
use the DriverObject (an argument the DriverEntry Takes )
and Set Breakpoints on each MAJORFunction
kd> bp . "du poi(#esi+1c+4);gc"
kd> bl
0 e Disable Clear 829d4b6a 0001 (0001) nt!IopLoadDriver
1 e Disable Clear 829d5355 0001 (0001) nt!IopLoadDriver+0x7ea "du poi(#esi+1c+4);gc"
kd> bd 0
kd> bl
0 d Enable Clear 829d4b6a 0001 (0001) nt!IopLoadDriver
1 e Disable Clear 829d5355 0001 (0001) nt!IopLoadDriver+0x7ea "du poi(#esi+1c+4);gc"
kd> g
841bd1d0 "\Driver\Null.Ѕ捁印䍁䥐停偎〰〰"
84f18718 "\Driver\Beep.Б浍摌䂈蓶䈸蓶...."
84eef210 "\Driver\VgaSave"
84eb2860 "\Driver\RDPCDDᛛ..В浍慃憠褎.蓫菌蓲"
84e903c0 "\Driver\RDPENCDD..浍摌읨蓤潤獷獜獹整.尲牤癩牥"
84e90400 "屳摲数据摤献獹"
84ef15c0 "\Driver\RDPREFMP..牉..蓧"
84ef4a78 "\FileSystem\Msfs.В浍慃冀褘蝴蓳荤蓶"
84f191f0 "\FileSystem\Npfs.З獍䑆.°"

Write windbg command output to file, but not console

In windbg, I'm looking for a mechanism to take the output of a command (specifically, a command inside of a breakpoint) and have it appended to a file, and not written to a console.
Currently I setup the process with .logappend C:\path\to\log and then enable a few breakpoints with:
bp WIN32U!{function} ".echo '===WIN32K-START==='; k; .echo '===WIN32K-END==='; g"
This works great, except the volume of output written to the console causes serious performance issues. I'm hopeful there's a way to get the same output to my log file, without the overhead of writing to the windbg console.
You want the .outmask meta-command: https://learn.microsoft.com/en-us/windows-hardware/drivers/debugger/-outmask--control-output-mask-
.outmask allows you to control which message types are sent to the output window and log file. The /l switch can allow you to change just the types that reach the output window, without affecting which types will reach the log file.
For example, this command will turn off all output to the output window while still sending normal messages to the log file:
.outmask- /l 0xffff
Although probably .outmask- /l 1 is all you need, which turns off just normal message output, but errors and warnings will still show up in the output window. Use .outmask /d to reset output settings back to the default when you're done.
In combination with the ability of .printf to output different message types, you can make it so you still have some idea what's going on, as well. Turn off normal message output to the window with .outmask- /l 1. Now you can use .printf /oe "message" in a breakpoint command somewhere to write an error message, which will still be sent to the output window so you can tell what's happening at certain points in the process.
you can patch dbgeng!g_OutputControl global to disable writing to console and only write to log file
but I don't know if you will have a performance gain or not
looking for a txt file
C:\>dir /b *.txt
File Not Found
opening a debugging session
C:\>cdb calc
Microsoft (R) Windows Debugger Version 10.0.15063.400 X86
ntdll!LdrpDoDebuggerBreak+0x2c:
774005a6 cc int 3
in the opened debugging session
spawn a parent debugger to debug the windbg running your debuggee
0:000> .dbgdbg
Debugger spawned, connect with
"-remote npipe:icfenable,pipe=cdb_pipe,server=xxxx"
in the spawned parent patch the global and detach
ed dbgeng!g_OutputControl 0
.detach
q
open a logfile in your debugging session
0:000> .logappend c:\foo.txt
Opened log file 'c:\foo.txt'
set a conditional breakpoint and start the session
0:000> bp ntdll!RtlEnterCriticalSection "kb;gc"
0:000> bl
0 e 773a7790 0001 (0001) 0:**** ntdll!RtlEnterCriticalSection "kb;gc"
0:000> g
there is no console output here
doing a ctrl+c to stop session and quitting the session
eax=7ffde000 ebx=00000000 ecx=00000000 edx=773ff1d3 esi=00000000 edi=00000000
eip=77394108 esp=016ef8a8 ebp=016ef8d4 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
ntdll!DbgBreakPoint:
77394108 cc int 3
0:001> q
quit:
check for the log file and confirm if it has voluminous data written to it
RtlEnterCriticalSection Api is a very hot Api
C:\>dir /b *.txt
foo.txt
C:\>ls -l foo.txt
-rw-rw-rw- 1 0 **1754920** 2017-09-15 00:27 foo.txt
C:>head foo.txt
Opened log file 'c:\foo.txt'
0:000> bp ntdll!RtlEnterCriticalSection "kb;gc"
0:000> bl
0 e 773a7790 0001 (0001) 0:**** ntdll!RtlEnterCriticalSection "kb;gc"
0:000> g
ChildEBP RetAddr Args to Child
000cf114 77425f4b 000d0138 7724d80b 00000000 ntdll!RtlEnterCriticalSection
000cf158 773ea40a 000d0000 50180162 00000044 ntdll!RtlDebugAllocateHeap+0x9d
000cf23c 773b5ae0 00000044 00000000 00000000 ntdll!RtlpAllocateHeap+0xc4
000cf2c0 77384726 000d0000 40180060 00000044 ntdll!RtlAllocateHeap+0x23a
there are more tha 22k lines written to this file
C:\>wc -l foo.txt
22543 foo.txt
C:>tail foo.txt
000cf838 773c37be 00462d6c 7ffdb000 00000000 ntdll!__RtlUserThreadStart+0x70
000cf850 00000000 00462d6c 7ffdb000 00000000 ntdll!_RtlUserThreadStart+0x1b
(c80.8ec): Break instruction exception - code 80000003 (first chance)
eax=7ffde000 ebx=00000000 ecx=00000000 edx=773ff1d3 esi=00000000 edi=00000000
eip=77394108 esp=016ef8a8 ebp=016ef8d4 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
ntdll!DbgBreakPoint:
77394108 cc int 3
0:001> q
quit:
C:\>

How does Windows locate files input in the shell?

I looked for this question over the site but it looks like it's never been asked, so I thought I would share the answer to anyone looking for it.
Q: When I input executables files' name in cmd.exe, through shell-execution functions or from a Batch file, how does Windows locate the external executable file to be called?
I do not understand what "shell-execution function" is referring to, so I will ignore it.
But the rules for launching an executable from the CMD.EXE command line, or from a batch file are as follows:
If a path is specified for the executable (absolute or relative), then only that path is searched.
If only the executable name (and possibly extension) is specified, then
First search the current folder
Then search folders in PATH environment variable (in order listed)
Within each folder searched, use the provided extension. If no file extension is provided, then look for files that match extensions found in PATHEXT environment variable (in order listed).
The first matching file found is the one that gets executed.
EDIT
David Candy has pointed me to some outdated NT documentation that precisely outlines the search process, and it essentially matches what I have written above. See Launching Applications from the NT Shell
I'd love it if anyone could post links to similar CMD.EXE documentation for more recent versions of Windows, especially if it was written by Microsoft. Note that the NT doc linked above was not written by Microsoft, even though it is posted on their site.
Here's a debug of CMD using CreateProcessW to start edit.com.
Microsoft (R) Windows Debugger Version 6.2.9200.20512 X86
Copyright (c) Microsoft Corporation. All rights reserved.
CommandLine: C:\Windows\System32\cmd.exe
Symbol search path is: srv*C:\tmp*http://msdl.microsoft.com/download/symbols;c:\tmp
Executable search path is:
ModLoad: 49fe0000 4a030000 cmd.exe
ModLoad: 76dd0000 76ef7000 ntdll.dll
ModLoad: 75860000 7593b000 C:\Windows\system32\kernel32.dll
ModLoad: 76a20000 76ae6000 C:\Windows\system32\ADVAPI32.dll
ModLoad: 76d00000 76dc2000 C:\Windows\system32\RPCRT4.dll
ModLoad: 75b20000 75bca000 C:\Windows\system32\msvcrt.dll
(58c.918): Break instruction exception - code 80000003 (first chance)
*** ERROR: Symbol file could not be found. Defaulted to export symbols for ntdll.dll -
eax=00000000 ebx=00000000 ecx=0027f9a0 edx=76e29a94 esi=fffffffe edi=76e2b6f8
eip=76e17dfe esp=0027f9b8 ebp=0027f9e8 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
ntdll!DbgBreakPoint:
76e17dfe cc int 3
0:000> bp kernel32!CreateProcessW
*** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\Windows\system32\kernel32.dll -
breakpoint 0 redefined
0:000> g
Breakpoint 0 hit
eax=0027f590 ebx=00000000 ecx=00000000 edx=00000000 esi=4a005200 edi=00000001
eip=75861c01 esp=0027f4b4 ebp=0027f674 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
kernel32!CreateProcessW:
75861c01 8bff mov edi,edi
0:000> kb
ChildEBP RetAddr Args to Child
WARNING: Stack unwind information not available. Following frames may be wrong.
0027f4b0 49fe4568 00316078 003175a8 00000000 kernel32!CreateProcessW
0027f674 49fe4315 00317508 00000000 00000000 cmd!ExecPgm+0x20a
0027f8d4 49fe43a8 00317508 00000000 00000000 cmd!ECWork+0x7f
0027f8ec 49fe43ce 00317508 e3a3ec47 00000001 cmd!ExtCom+0x47
0027fd48 49fe185f 00317508 00000002 7588372f cmd!FindFixAndRun+0xb3
0027fd98 49ff70d4 00000000 00317508 4a0041b0 cmd!Dispatch+0x14a
0027fddc 49fe985b 00000001 000a0f38 000a1840 cmd!main+0x21a
0027fe20 758a4911 7ffdb000 0027fe6c 76e0e4b6 cmd!_initterm_e+0x163
0027fe2c 76e0e4b6 7ffdb000 7871d1d4 00000000 kernel32!BaseThreadInitThunk+0x12
0027fe6c 76e0e489 49fe9797 7ffdb000 00000000 ntdll!RtlInitializeExceptionChain+0x63
0027fe84 00000000 49fe9797 7ffdb000 00000000 ntdll!RtlInitializeExceptionChain+0x36
0:000> du 316078
00316078 "C:\Windows\system32\edit.com"
See CreateProcess.
The directory from which the application loaded.
The current directory for the parent process.
The 32-bit Windows system directory. Use the GetSystemDirectory function to get the path of this directory.
Windows Me/98/95: The Windows system directory. Use the GetSystemDirectory function to get the path of this directory.
The 16-bit Windows system directory. There is no function that obtains the path of this directory, but it is searched. The name of this directory is System.
The Windows directory. Use the GetWindowsDirectory function to get the path of this directory.
The directories that are listed in the PATH environment variable. Note that this function does not search the per-application path specified by the App Paths registry key. To include this per-application path in the search sequence, use the ShellExecute function.

How to view c# variables using windbg

I have a C# windows service installed on a 32 bit windows server 2003 machine that I wish to debug.
The problem I have is that a log file error message tells me the following:
System.NullReferenceException: Object reference not set to an instance of an object.
at VideoProcessor.ResetCameraProperties(DataServiceObject dso)
at VideoProcessor.AddServer(DataServiceObject dso)
at VideoProcessor.LoadServers()
at VideoProcessor.Start()
atVideoServerComponent.Connect()
The actual code for the function ResetCameraProperties is:
protected void ResetCameraProperties(DataServiceObject dso)
{
// Find the CameraType.
//Type videoCameraType = TypeManager.Instance["XFire.Common.VideoObjects.VideoServer"];
if (_videoCameraType == null) return;
//Load cameras from the Data Service Layer
string whereClause = "ServerID = ?";
object[] args = new object[] { dso["ObjectID"] };
IDataServiceCollection videoCameraDsoCollection = ClientServerConnection.Instance.FindCollection(_videoCameraType, whereClause, args, null, CollectionOptions.FilterByPartitionResponsibility) as IDataServiceCollection;
if (videoCameraDsoCollection == null || 0 == videoCameraDsoCollection.Count)
return;
videoCameraDsoCollection.LoadContainerOnEnumeration = false;
foreach (DataServiceObject camera in videoCameraDsoCollection)
{
if (!(bool)dso[RecorderKey.Online] && (int)dso[RecorderKey.VideoServerAlarm] == (int)VideoServerComponent.GetVideoServerAlarm("Offline"))
{
// If the server is disconnected, then we know everything should be offline.
camera[CameraKey.VideoCameraAlarm] = VideoServerComponent.GetEnumValueOfType("XFire.Common.VideoObjectDefinitions.VideoCameraAlarm", "Unknown");
camera[CameraKey.Videoloss] = true;
}
else if ((bool)dso[RecorderKey.Online] && (int)dso[RecorderKey.VideoServerAlarm] == (int)VideoServerComponent.GetVideoServerAlarm("Online"))
{
camera[CameraKey.VideoCameraAlarm] = VideoServerComponent.GetEnumValueOfType("XFire.Common.VideoObjectDefinitions.VideoCameraAlarm", "Normal");
camera[CameraKey.Videoloss] = false;
}
// Save the camera.
ServerResult result = ClientServerConnection.Instance.PersistObject(camera, null);
if (result.Fault != null)
{
if (VideoTrace.TraceError) Trace.WriteLine(result.Fault.Message);
}
}
I have opened windbg and did File-->Attach to process
I have set breakpoints in the function above using the steps outlined here: https://learn.microsoft.com/en-us/archive/blogs/alejacma/managed-debugging-with-windbg-preparing-the-environment
When the breakpoint is hit I step forward using F10 but all I see is the following:
Setting breakpoint: bp 05A0A260 [VideoProcessor.*ResetCameraProperties (XFire.Common.DataServiceLayer.DataServiceObject)]
Adding pending breakpoints...
0:024> g
DriverWindowsService.OnStop Service stopping...
Breakpoint 0 hit
eax=00000001 ebx=00902870 ecx=00a1e020 edx=01066e78 esi=00affb48 edi=01066e78
eip=05a0a260 esp=0674e68c ebp=0674e6b0 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
05a0a260 55 push ebp
0:024> p
eax=00000001 ebx=00902870 ecx=00a1e020 edx=01066e78 esi=00affb48 edi=01066e78
eip=05a0a261 esp=0674e688 ebp=0674e6b0 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
05a0a261 8bec mov ebp,esp
0:024> p
eax=00000001 ebx=00902870 ecx=00a1e020 edx=01066e78 esi=00affb48 edi=01066e78
eip=05a0a263 esp=0674e688 ebp=0674e688 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
05a0a263 57 push edi
This means nothign to me at present (I'm a windbg newbie)
I have the pdb file for the windows service (I got from the Visual Studio Debug Output folder) and have copied itto my target machine in a folder C:\Symbols.
In winDbg I did File-->Symbol FIle path and set it to the location of this pdb file I copied over. My symbol path is as follows:
C:\symcache;C:\Symbols;srvc:\symcachehttp://msdl.microsoft.com/download/symbols
In Windbg I did View-->Watch and I typed in the name of a variable that is inside the function above (videoCameraType). But I got the following error:
*** Either you specified an unqualified symbol, or your debugger ***
*** doesn't have full symbol information. Unqualified symbol ***
*** resolution is turned off by default. Please either specify a ***
*** fully qualified symbol module!symbolname, or enable resolution ***
*** of unqualified symbols by typing ".symopt- 100". Note that ***
*** enabling unqualified symbol resolution with network symbol ***
*** server shares in the symbol path may cause the debugger to ***
*** appear to hang for long periods of time when an incorrect ***
*** symbol name is typed or the network symbol server is down. ***
*** For some commands to work properly, your symbol path ***
*** must point to .pdb files that have full type information. ***
*** Certain .pdb files (such as the public OS symbols) do not ***
*** contain the required information. Contact the group that ***
*** provided you with these symbols if you need this command to ***
*** work. ***
*** Type referenced: _videoCameraType ***
How can I view variables and generally see what is going on in my code????
I also have the source code for the windows service if thats any help.
Thanks
First thing is that your symbol files are probably not matching binaries as there is no source file paths and line numbers in your exception stack trace. You mentioned that you copied them from the Visual Studio Debug Output, so I assume that you have binaries compiled in Release (with no symbols) and pdb files from Debug. This won't work. What you need to do is change the project settings for your service, recompile and deploy it (you should now have pdb, dll and exe files in the release output folder). This should generate a much more meaningful stack trace for your exception.
Now, the second part. You need to distinguish a managed environment from the native one. In windbg you are debugging the CLR as it is seen by the operating system, thus you are debugging not only your C# application but the CLR interpreter that compiles your ILASM (compiled C# code) to native CPU instructions and then executes them. So you are a layer below what you normally see in VS (with managed debugger attached). Keeping that in mind you need to either dig into CLR internals and try to figure out what the addresses in registers mean or use some sort of translator which will do this heavy work for you. And this is where SOS comes into play. You've already used it when you set the breakpoint. As you are only interested in knowing a value of your variable you need to first find out at what address the CLR lied it out for you. From what I see the _videoCameraType is a private class member, isn't it? If so you may dump managed objects from the stack using !dso command. You should see something similar to the output below:
> !dso
OS Thread Id: 0xad8 (0)
RSP/REG Object Name
000000000068E8F0 00000000025f2bc8 Program+Test
000000000068E8F8 00000000025f2be0 System.String test
000000000068E910 00000000025f2bc8 Program+Test
000000000068E918 00000000025f2bc8 Program+Test
where Program+Test would be replaced by your class name. Then you may dump the object content using !do command and the address from the Object column:
> !do 00000000025f2bc8
Name: Program+Test
MethodTable: 000007fe58333a08
EEClass: 000007fe584422b8
Size: 24(0x18) bytes
File: D:\temp\Test.exe
Fields:
MT Field Offset Type VT Attr Value Name
000007feb4dcb318 4000001 8 System.String 0 instance 00000000025f2be0 _testVariable
Find the class member by its name and use !do command once again but using address from the Value column (this works for reference types). In our example it would be:
0:000> !do 00000000025f2be0
Name: System.String
MethodTable: 000007feb4dcb318
EEClass: 000007feb4733720
Size: 34(0x22) bytes
File: C:\Windows\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
String: test
Fields:
MT Field Offset Type VT Attr Value Name
000007feb4dce0c8 40000aa 8 System.Int32 1 instance 4 m_stringLength
000007feb4dcc600 40000ab c System.Char 1 instance 74 m_firstChar
000007feb4dcb318 40000ac 18 System.String 0 shared static Empty
>> Domain:Value 000000000074f960:NotInit <<
Things get trickier if you need to figure out what a value of a local variable is. You may try with !CLRStack -a which usually does not show much in release builds. You are then left with analysis of the generated assembly (!U #rip) in order to find out where the address of your variables landed (registry, stack). After figuring this out, issue again the !do command with the address you've found. Happy debugging :)
Adding to this thread since it shows up in Google searches:
The following worked for me:
(If application uses .net 4 use .loadby sos clr to load the SOS debugger extension)
Once you are on the right thread first use !clrstack -p to dump the stack along with the addresses of the local variables.
Now use the address of the local variable of interest to dump it using !do .
Then using the addresses from the output that you get - you can use !do again (use the Value field here for the address of a specific member). You can continue till you are able to see the value you desire.
(You can also use this approach to dump members of the "this" pointer which you obtain from the stack. This may have some variables of interest based on what you are looking for)
See http://blogs.msdn.com/b/alejacma/archive/2009/08/11/managed-debugging-with-windbg-thread-stacks-part-1.aspx
Debugging is exciting! Have fun with it!

How to break into WinDBG when ntdll.dll is mapped into the new process

I want to use the following command to break into WinDBG when ntdll.dll is mapped into the new process, and before any of ntdll's process initialization runs.
sxe ld ntdll.dll ;g
However, the trick doesn't work at all,
ModLoad: 7c900000 7c9b0000 ntdll.dll
eax=010043af ebx=7ffde000 ecx=020f18f5 edx=00000034 esi=00c2f720 edi=00c2f6f2
eip=7c810867 esp=0006fffc ebp=00000720 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00000200
7c810867 ?? ???
Processing initial command 'sxe ld ntdll.dll ;g'
0:000> sxe ld ntdll.dll ;g
(ae8.6f4): Break instruction exception - code 80000003 (first chance)
eax=00181eb4 ebx=7ffde000 ecx=00000001 edx=00000002 esi=00181f48 edi=00181eb4
eip=7c901230 esp=0006fb20 ebp=0006fc94 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
ntdll!DbgBreakPoint:
7c901230 cc int 3
So, How to break into WinDBG when ntdll.dll is mapped into the new process?
thanks
[UPDATE]
I exactly followed the steps as mentioned by jcopenha, but I don't know why Windbg gives a strange error(Memory access error) where Notepad.exe is running .
Please give me a hand!Thanks a lot!
0:000> .restart /f
CommandLine: C:\WINDOWS\NOTEPAD.EXE
Symbol search path is: D:\Symbols\Symbols;SRV*D:\Symbols\MySymbols*http://msdl.microsoft.com/download/symbols
Executable search path is:
ModLoad: 01000000 01014000 notepad.exe
eax=0100739d ebx=7ffd9000 ecx=020f18f5 edx=0000004e esi=00f7f73a edi=00f7f6f2
eip=7c810867 esp=0007fffc ebp=0000024c iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00000200
7c810867 ?? ???
0:000> u 7c810867
7c810867 ?? ???
^ Memory access error in 'u 7c810867'
[UPDATE2]
I found an odd instruction displayed at 7c810867, but p command still can work.
Is it a bug in WinDBG?
If you go to Debug->Event Filters and change "Create process" to "enabled" then restart the application it will start before ntdll.dll shows up in the module list. If you then do sxe ld ntdll.dll;g it will stop in ntdll!RtlUserThreadStart.
0:000> .restart /f
CommandLine: C:\Windows\System32\notepad.exe
Symbol search path is: SRV*d:\symbols*http://msdl.microsoft.com/download/symbols
Executable search path is:
ModLoad: 00000000`ffe00000 00000000`ffe35000 notepad.exe
00000000`7790c500 4883ec48 sub rsp,48h
0:000> sxe ld ntdll.dll;g
ModLoad: 00000000`778e0000 00000000`77a89000 ntdll.dll
ntdll!RtlUserThreadStart:
00000000`7790c500 4883ec48 sub rsp,48h
Regarding the loading of ntdll, I recommend reading this. You can break into the process before any code runs with:
windbg -xe cpr notepad
Or
windbg -xe ld:ntdll notepad
ntdll will still be mapped into the process at this point -- you can't break in before this happens.
As for the memory access error, kernel32 is not loaded into the process yet. The initial thread is queued to run at kernel32!BaseProcessStartThunk, but since kernel32 isn't loaded into the address space yet, you aren't going to see anything at that address.
The reason the thread's start address is able to begin in unmapped memory is because before the thread begins its execution, the very first thing that happens is a user APC runs in the context of that initial thread that takes care of all the process initialization, including loading kernel32. You can see this event occur if you set a similar event, like:
sxe ld kernel32
You will need to load symbols to get the internal functions names in the stack trace.
In addition to the first link, you can read more about process initialization here. Hope this helps.
As far as I remember ntdll is not mapped by the user-mode. If it was mapped in by the user-mode, what would map the module that maps ntdll? ntdll contains a set of stubs for syscalls to enter into the kernel and also contains a few other things such as a COFF loader which is part of process initialisation. It is a bit of a magic dll and it cannot be relocated, thus is always at the same virtual address in every process.
If you want to break before ntdll is mapped I am afraid you will have to use a kernel debugger.
May I ask what you are trying to achieve by breaking before ntdll is mapped?

Resources