Windbg script: Is there a way to have the currently executed command outputted to the log? - windbg

I'm using cdb with a script file to process crashing inputs to a process (I don't collect dumps).
The command line for cdb is as follow:
PS> & "C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\cdb.exe" -g -logo K:\_projects\fuzz\out_test.txt -c "`$`$><K:\_projects\fuzz\crash_info_script.wsc" "K:\_projects\fuzz\bin\simpleTest.exe" -f "K:\_projects\fuzz\corpus\crashes\test_00000000.bin"
The script file (crash_info_script.wsc in the above command line) passed to cdb is simple, as I just want basic info:
!analyze -v; .exr -1; lm; k; lmDvmsimpleTest; qq
The problem is that the commands themselves are not in the output log. For example, in the latter I have (output of .exr -1 and lm):
ExceptionAddress: 00007ffe75721f3e (simpleTest!foo+0x0000000000290f7e)
ExceptionCode: c0000005 (Access violation)
ExceptionFlags: 00000000
NumberParameters: 2
Parameter[0]: 0000000000000000
Parameter[1]: 000001a435a25000
Attempt to read from address 000001a435a25000
start end module name
00007ff6`df020000 00007ff6`df07d000 simpleTest C (export symbols) K:\_projects\fuzz2\bin\simpleTest.exe
00007ffe`75250000 00007ffe`7686a000 foo (export symbols) K:\_projects\fuzz2\bin\foo.dll
00007ffe`ac530000 00007ffe`ac5ce000 uxtheme (deferred)
00007ffe`aeb10000 00007ffe`aeb41000 cryptnet (deferred)
00007ffe`aeb50000 00007ffe`aeb5a000 VERSION (deferred)
00007ffe`b5230000 00007ffe`b5242000 kernel_appcore (deferred)
00007ffe`b6c50000 00007ffe`b6c5c000 cryptbase (deferred)
00007ffe`b6ce0000 00007ffe`b6d0c000 wldp (deferred)
00007ffe`b6f40000 00007ffe`b6f52000 msasn1 (deferred)
00007ffe`b7100000 00007ffe`b7134000 devobj (deferred)
00007ffe`b74a0000 00007ffe`b75ff000 CRYPT32 (deferred)
...
What I would like:
> .exr -1
ExceptionAddress: 00007ffe75721f3e (simpleTest!foo+0x0000000000290f7e)
ExceptionCode: c0000005 (Access violation)
ExceptionFlags: 00000000
NumberParameters: 2
Parameter[0]: 0000000000000000
Parameter[1]: 000001a435a25000
Attempt to read from address 000001a435a25000
> lm
start end module name
00007ff6`df020000 00007ff6`df07d000 simpleTest C (export symbols) K:\_projects\fuzz2\bin\simpleTest.exe
00007ffe`75250000 00007ffe`7686a000 foo (export symbols) K:\_projects\fuzz2\bin\foo.dll
00007ffe`ac530000 00007ffe`ac5ce000 uxtheme (deferred)
00007ffe`aeb10000 00007ffe`aeb41000 cryptnet (deferred)
00007ffe`aeb50000 00007ffe`aeb5a000 VERSION (deferred)
00007ffe`b5230000 00007ffe`b5242000 kernel_appcore (deferred)
00007ffe`b6c50000 00007ffe`b6c5c000 cryptbase (deferred)
00007ffe`b6ce0000 00007ffe`b6d0c000 wldp (deferred)
00007ffe`b6f40000 00007ffe`b6f52000 msasn1 (deferred)
00007ffe`b7100000 00007ffe`b7134000 devobj (deferred)
00007ffe`b74a0000 00007ffe`b75ff000 CRYPT32 (deferred)
...
I could use .printf after each command but this is quite inconvenient, especially if I change the script.

I dont have a fuzzable executable this is from a dump so i cant be sure if the behaviour you see is because of that.
use -cfr file command instead of -c and try
pre dir contents
D:\niet>ls -lg
total 153021
-rw-r--r-- 1 197121 156689581 Aug 17 23:49 MEMORY.DMP
-rw-r--r-- 1 197121 22 Sep 17 16:09 foo.wds
D:\niet>file MEMORY.DMP
MEMORY.DMP: MS Windows 64bit crash dump, 4992030524978970960 pages
D:\niet>cat foo.wds
!analyze -v
lm
kb
q
command used
D:\niet>cdb -g -logo foo.txt -cfr foo.wds -z MEMORY.DMP
debugger
Microsoft (R) Windows Debugger Version 10.0.17763.132 AMD64
post dir contents
D:\niet>ls -lg
total 153053
-rw-r--r-- 1 197121 156689581 Aug 17 23:49 MEMORY.DMP
-rw-r--r-- 1 197121 29738 Sep 17 16:19 foo.txt
-rw-r--r-- 1 197121 22 Sep 17 16:09 foo.wds
looking for executed commands
D:\niet>cat foo.txt | grep -i ": kd"
1: kd> !analyze -v
1: kd> lm
1: kd> kb
1: kd> q

Related

WinDbg "Failed to load data access DLL"

there is a .NET application that seems to have memory leak in the unmanaged heap. I found a promising blog that explains how to debug the unmanaged heap and trace the heap frames up to the managed functions that caused the memory allocation (https://www.deleaker.com/blog/2021/03/19/unmanaged-memory-leaks-in-dotnet/). As I'm a first time windbg user, I decided to repeat the example shown in the blog. I copypasted the code, downloaded the debug tool package and used the windbg as suggested. Here is whgere I get stuck:
Microsoft (R) Windows Debugger Version 10.0.22000.194 AMD64
Copyright (c) Microsoft Corporation. All rights reserved.
*** wait with pending attach
************* Path validation summary **************
Response Time (ms) Location
Deferred srv*
Symbol search path is: srv*
Executable search path is:
ModLoad: 00000000`00120000 00000000`00128000 C:\<MyPath>\WinDbgTest.exe
ModLoad: 00007ffe`c4c10000 00007ffe`c4e05000 C:\WINDOWS\SYSTEM32\ntdll.dll
ModLoad: 00000000`77800000 00000000`779a3000 ntdll.dll
ModLoad: 00007ffe`c3180000 00007ffe`c31d9000 C:\WINDOWS\System32\wow64.dll
ModLoad: 00007ffe`c30d0000 00007ffe`c3153000 C:\WINDOWS\System32\wow64win.dll
ModLoad: 00000000`777f0000 00000000`777fa000 C:\WINDOWS\System32\wow64cpu.dll
ModLoad: 00000000`74890000 00000000`748e2000 mscoree.dll
ModLoad: 00000000`75e50000 00000000`75f40000 KERNEL32.dll
ModLoad: 00000000`76f40000 00000000`77154000 KERNELBASE.dll
ModLoad: 00000000`756b0000 00000000`7572a000 ADVAPI32.dll
ModLoad: 00000000`75730000 00000000`757ef000 msvcrt.dll
ModLoad: 00000000`75be0000 00000000`75c55000 SECHOST.dll
ModLoad: 00000000`76610000 00000000`766d0000 RPCRT4.dll
ModLoad: 00000000`74760000 00000000`747ed000 mscoreei.dll
ModLoad: 00000000`766d0000 00000000`76715000 SHLWAPI.dll
ModLoad: 00000000`74750000 00000000`7475f000 AppCore.dll
ModLoad: 00000000`74e30000 00000000`74e38000 VERSION.dll
ModLoad: 00000000`707a0000 00000000`70f50000 clr.dll
ModLoad: 00000000`75890000 00000000`75a26000 USER32.dll
ModLoad: 00000000`774e0000 00000000`774f8000 win32u.dll
ModLoad: 00000000`705b0000 00000000`7065b000 ucrtbase_clr0400.dll
ModLoad: 00000000`70660000 00000000`70674000 VCRUNTIME140_CLR0400.dll
ModLoad: 00000000`76ec0000 00000000`76ee3000 GDI32.dll
ModLoad: 00000000`75c60000 00000000`75d3c000 gdi32full.dll
ModLoad: 00000000`76810000 00000000`7688b000 msvcp_win.dll
ModLoad: 00000000`75a30000 00000000`75b50000 ucrtbase.dll
ModLoad: 00000000`75f50000 00000000`75f75000 IMM32.dll
ModLoad: 00000000`6f180000 00000000`7058e000 mscorlib.ni.dll
ModLoad: 00000000`76060000 00000000`76143000 ole32.dll
ModLoad: 00000000`77560000 00000000`777e2000 combase.dll
ModLoad: 00000000`76e50000 00000000`76ead000 bcryptPrimitives.dll
ModLoad: 00000000`6f0f0000 00000000`6f17a000 clrjit.dll
ModLoad: 00000000`757f0000 00000000`75886000 OLEAUT32.dll
(745c.6ac0): Break instruction exception - code 80000003 (first chance)
ntdll!DbgBreakPoint:
00007ffe`c4cb0810 cc int 3
0:005> !heap -s
************************************************************************************************************************
NT HEAP STATS BELOW
************************************************************************************************************************
NtGlobalFlag enables following debugging aids for new heaps:
stack back traces
LFH Key : 0xca6fcf0f30c2eb6b
Termination on corruption : ENABLED
Heap Flags Reserv Commit Virt Free List UCR Virt Lock Fast
(k) (k) (k) (k) length blocks cont. heap
-------------------------------------------------------------------------------------
0000000001db0000 08000002 60 32 60 11 5 1 0 0
0000000000150000 08008000 64 4 64 2 1 1 0 0
-------------------------------------------------------------------------------------
0:005> !heap -stat -h 0000000001db0000
heap # 0000000001db0000
group-by: TOTSIZE max-display: 20
size #blocks total ( %) (percent of total busy bytes)
2094 1 - 2094 (48.69)
838 1 - 838 (12.28)
800 1 - 800 (11.96)
120 5 - 5a0 (8.41)
1d8 2 - 3b0 (5.51)
100 3 - 300 (4.48)
238 1 - 238 (3.32)
50 4 - 140 (1.87)
42 3 - c6 (1.16)
3c 2 - 78 (0.70)
62 1 - 62 (0.57)
48 1 - 48 (0.42)
30 1 - 30 (0.28)
28 1 - 28 (0.23)
10 1 - 10 (0.09)
4 1 - 4 (0.02)
0:005> !heap -flt s 2094
_HEAP # 1db0000
HEAP_ENTRY Size Prev Flags UserPtr UserSize - state
0000000001db10c0 020c 0000 [00] 0000000001db10f0 02094 - (busy)
unknown!printable
_HEAP # 150000
0:005> !heap -p -a 0000000001db10f0
address 0000000001db10f0 found in
_HEAP # 1db0000
HEAP_ENTRY Size Prev Flags UserPtr UserSize - state
0000000001db10c0 020c 0000 [00] 0000000001db10f0 02094 - (busy)
unknown!printable
7ffec4c3b49d ntdll!RtlpAllocateHeapInternal+0x0000000000000a7d
7ffec4c5dce1 ntdll!RtlpInitEnvironmentBlock+0x0000000000000049
7ffec4ce27c1 ntdll!LdrpInitializeProcess+0x0000000000000ba1
7ffec4c84ceb ntdll!LdrpInitialize+0x000000000000015f
7ffec4c84b73 ntdll!LdrpInitialize+0x000000000000003b
7ffec4c84b1e ntdll!LdrInitializeThunk+0x000000000000000e
0:005> .load C:\<DllPath>\WinDbgDlls\sos.dll
0:005> !ip2md 7ffec4c84b1e
Failed to load data access DLL, 0x80004005
Verify that 1) you have a recent build of the debugger (6.2.14 or newer)
2) the file mscordacwks.dll that matches your version of clr.dll is
in the version directory or on the symbol path
3) or, if you are debugging a dump file, verify that the file
mscordacwks_<arch>_<arch>_<version>.dll is on your symbol path.
4) you are debugging on supported cross platform architecture as
the dump file. For example, an ARM dump file must be debugged
on an X86 or an ARM machine; an AMD64 dump file must be
debugged on an AMD64 machine.
You can also run the debugger command .cordll to control the debugger's
load of mscordacwks.dll. .cordll -ve -u -l will do a verbose reload.
If that succeeds, the SOS command should work on retry.
If you are debugging a minidump, you need to make sure that your executable
path is pointing to clr.dll as well.
0:005> .cordll -ve -u -l
CLR DLL status: No load attempts
Everything seems to work until I call !ip2md, here comes a "Failed to load data access DLL". Following some google results I have put the clr.dll, SOS.dll and mscordacwks.dll in one folder and made sure that they all have the same bitness and the same version.
How to proceed?
Instead of loading a specific version of SOS located somewhere on your PC, let .NET decide which version to load.
Replace
.load C:\<DllPath>\WinDbgDlls\sos.dll
by
.loadby sos clr
This tells WinDbg to load the SOS extension from whatever place CLR was loaded from. This will make sure that the versions match and the DAC matches as well.
.loadby may depend on the .NET version
.loadby sos mscorwks ; *** .NET 2
.loadby sos clr ; *** .NET 4
.loadby sos coreclr ; *** Silverlight and .NET Core

NTDLL symbols available but !address does not work

I'm trying to do basic debugging with WinDbg but I'm stuck at the beginning since my environment cannot find the symbols for ntdll and those are essential for the !address command:
0:000> !address
No symbols for ntdll. Cannot continue.
The weird thing is that using lm I can see that the debugger aware of the symbol file! So why it can't use this file? This file was imported using symchk utility so it supposed to be the right symbol file.
Here is the command window output:
0:000> .sympath
Symbol search path is: srv*C:\Symbols*http://msdl.microsoft.com/download/symbols
Expanded Symbol search path is: srv*c:\symbols*http://msdl.microsoft.com/download/symbols
************* Path validation summary **************
Response Time (ms) Location
Deferred srv*C:\Symbols*http://msdl.microsoft.com/download/symbols
0:000> lm
start end module name
007b0000 007db000 notepad (no symbols)
71b50000 71d5f000 COMCTL32 (deferred)
747b0000 747ba000 CRYPTBASE (deferred)
747c0000 747e0000 SspiCli (deferred)
747e0000 748ff000 ucrtbase (deferred)
749c0000 74a39000 advapi32 (deferred)
74a40000 74afb000 RPCRT4 (deferred)
74db0000 74fac000 KERNELBASE (pdb symbols) c:\symbols\wkernelbase.pdb\8BC9719D7B1E26272FB1CB98D403792C1\wkernelbase.pdb
75120000 7517f000 bcryptPrimitives (deferred)
75200000 75276000 sechost (deferred)
75330000 75347000 win32u (deferred)
757a0000 7585f000 msvcrt (deferred)
76430000 7658a000 gdi32full (deferred)
76590000 76727000 USER32 (deferred)
76730000 767ac000 msvcp_win (deferred)
768c0000 769a0000 KERNEL32 (deferred)
76aa0000 76b24000 shcore (deferred)
76c50000 76ec6000 combase (deferred)
76fb0000 76fd1000 GDI32 (deferred)
76ff0000 7718a000 ntdll (pdb symbols) c:\symbols\wntdll.pdb\D85FCE08D56038E2C69B69F29E11B5EE1\wntdll.pdb
You can see that the location of the symbol file is identified (lm command output) But it claims no symbol are found.
More interesting, WinDbg can show me the symbols of functions inside ntdll binary:
0:000> x ntdll!*Virtual*
76ff44c0 ntdll!RtlpQueryReadVirtualMemory (void)
76f9bcc7 ntdll!RtlpSecMemFreeVirtualMemory (void)
76fb2df0 ntdll!NtLockVirtualMemory (<no parameter info>)
76fb1fa0 ntdll!ZwQueryVirtualMemory (<no parameter info>)
76fb2bd0 ntdll!NtFlushVirtualMemory (<no parameter info>)
76fb36f0 ntdll!ZwSetInformationVirtualMemory (<no parameter info>)
...
But still, whenever I try to use the !address command I have the same error.

erlang os:cmd() command with UTF8 binary

I'm trying to get an Erlang function to execute a bash command containing unicode characters. For example, I want to execute the equivalent of:
touch /home/jani/ჟანიweł
I put that command in variable D, for example:
io:fwrite("~ts", [list_to_binary(D)]).
touch /home/jani/ჟანიwełok
but after I execute:
os:cmd(D)
I get file called á??á??á??á??weÅ?. How can I fix it?
os:cmd(binary_to_list(unicode:characters_to_binary("touch /home/jani/编程"))).
Executing this command creates a file named ��, while executing the equivalent touch command directly in a terminal creates the file with the correct name.
Its because Erlang reads your source files like latin1 by default, but on newer versions of erlang you can set your files to use unicode.
%% coding: utf-8
-module(test).
-compile(export_all).
test() ->
COMMAND = "touch ჟანიweł",
os:cmd(COMMAND).
and then compiling and executing the module works fine
rorra-air:~ > erl
Erlang/OTP 17 [erts-6.4] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]
Eshell V6.4 (abort with ^G)
1> c(test).
{ok,test}
2> test:test().
[]
and it created the file on my filesystem
rorra-air:~ > ls -lta
total 144
-rw-r--r-- 1 rorra staff 0 Jun 9 15:18 ჟანიweł

Bad symbols for NTDLL (error 3). Aborting

What could cause the error:
Bad symbols for NTDLL (error 3). Aborting.
While using !cs commands?
I'm analyzing a keyboard-forced complete dump and have set the symbol path to the MS symbol server.
lml does not list ntdll as loaded
.sym noisy and a reload shows:
3: kd> .reload ntdll
"ntdll" was not found in the image list.
Debugger will attempt to load "ntdll" at given base 00000000`00000000.
Please provide the full image name, including the extension (i.e. kernel32.dll)
for more reliable results.Base address and size overrides can be given as
.reload <image.ext>=<base>,<size>.
DBGENG: ntdll - Partial symbol image load missing image info
DBGHELP: No header for ntdll. Searching for dbg file
DBGHELP: .\ntdll.dbg - file not found
DBGHELP: ntdll missing debug info. Searching for pdb anyway
DBGHELP: Can't use symbol server for ntdll.pdb - no header information available
DBGHELP: ntdll.pdb - file not found
DBGHELP: ntdll - no symbols loaded
Unable to add module at 00000000`00000000
3: kd> .reload nt
DBGHELP: nt - public symbols
c:\symbols\ntkrnlmp.pdb\BF9E190359784C2D8796CF5537B238B42\ntkrnlmp.pdb
Should ntdll be listed in the lm commands?
Is there something special needed to load the symbols or run these commands?
Additionally I am also curious why I cannot dump all threads in forced/complete system dumps:
3: kd> ~* k
^ Syntax error in '~* k'
Have I simply failed to set up my windbg correctly or are these commands meant for other types of dumps?
It seems you have done user mode debugging before. Now you're in kernel mode, which you can see from the x: kd> prompt.
Kernel mode debugging is somewhat different to user mode debugging. Most important IMHO: not all application memory (virtual memory) is available, just the part that was in RAM at the time of the dump (physical memory) aka. Working Set (physical memory of a particular process).
You can search for your executable using !process 0 0 <exename>
0: kd> !process 0 0 NotMyFault.exe
PROCESS ff3b58f0 SessionId: 0 Cid: 05ac Peb: 7ffde000 ParentCid: 039c
DirBase: 018c02e0 ObjectTable: e165d728 HandleCount: 35.
Image: NotMyfault.exe
Unfortunately there is no wildcard search possible at this point. You can then switch to that process using .process <process>:
0: kd> .process ff3b58f0
Implicit process is now ff3b58f0
To see the threads use !process <process> 2:
0: kd> !process ff3b58f0 2
PROCESS ff3b58f0 SessionId: 0 Cid: 05ac Peb: 7ffde000 ParentCid: 039c
DirBase: 018c02e0 ObjectTable: e165d728 HandleCount: 35.
Image: NotMyfault.exe
THREAD ff1d4020 Cid 05ac.05b0 Teb: 7ffdd000 Win32Thread: e1c6e2b0 RUNNING on processor 0
Next, use !thread <thread> to get output similar to ~:
0: kd> !thread ff1d4020
THREAD ff1d4020 Cid 05ac.05b0 Teb: 7ffdd000 Win32Thread: e1c6e2b0 RUNNING on processor 0
IRP List:
81942f68: (0006,0094) Flags: 40000000 Mdl: 00000000
Not impersonating
DeviceMap e169ffd0
Owning Process 0 Image: <Unknown>
Attached Process ff3b58f0 Image: NotMyfault.exe
Wait Start TickCount 13575 Ticks: 0
Context Switch Count 653 IdealProcessor: 0 LargeStack
UserTime 00:00:00.000
KernelTime 00:00:00.078
Win32 Start Address NotMyfault (0x01002945)
Start Address kernel32!BaseProcessStartThunk (0x7c8106f5)
Stack Init f36f1000 Current f36f030c Base f36f1000 Limit f36ec000 Call 0
Priority 9 BasePriority 8 PriorityDecrement 0 DecrementCount 16
ChildEBP RetAddr Args to Child
f36f0ad0 8052036a 00000050 81617000 00000001 nt!KeBugCheckEx+0x1b (FPO: [Non-Fpo])
f36f0b38 80544578 00000001 81617000 00000000 nt!MmAccessFault+0x9a8 (FPO: [Non-Fpo])
f36f0b38 fca6161d 00000001 81617000 00000000 nt!KiTrap0E+0xd0 (FPO: [0,0] TrapFrame # f36f0b50)
f36f0bd8 fca61a24 81942f68 f36f0c1c fca61b26 myfault+0x61d
f36f0be4 fca61b26 80fa7350 00000001 00000000 myfault+0xa24
f36f0c1c 804ef18f 80f7b600 81942f68 806e6428 myfault+0xb26
...
If you have trouble loading symbols, also try .reload /user after using the .process <process>.

Schrödinger's file

I am puzzled by the following sequence of commands.
sh-4.2$ pwd
/home/willard
sh-4.2$ ls -l f
-rwxr-xr-x 1 willard users 59116 Jan 23 14:54 f
sh-4.2$ file f
f: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.15, BuildID[sha1]=0xea0e08ff2b5a062698d45b78177acdd6bf140d1f, stripped
sh-4.2$ ./f
sh: ./f: No such file or directory
sh-4.2$ strace ./f
execve("./f", ["./f"], [/* 32 vars */]) = -1 ENOENT (No such file or directory)
write(2, "strace: exec: No such file or di"..., 40strace: exec: No such file or directory
) = 40
exit_group(1) = ?
+++ exited with 1 +++
sh-4.2$ ls -l f
-rwxr-xr-x 1 willard users 59116 Jan 23 14:54 f
sh-4.2$ uname -a
Linux xdat10 3.6.2-1-ARCH #1 SMP PREEMPT Fri Oct 12 23:58:58 CEST 2012 x86_64 GNU/Linux
How is this possible?
I found someone having the same problem (with relative explanation)
Running 32bit binary on a 64bit system
Quoting the most important sentences:
This situation often arises when you try to run a binary for the right
system (or family of systems) and superarchitecture but the wrong
subarchitecture. Here you have ELF binaries on a system that expects
ELF binaries, so the kernel loads them just fine. They are i386
binaries running on an x86_64 processor, so the instructions make
sense and get the program to the point where it can look for its
loader. But the program is a 32-bit program (as the file output
indicates), looking for the 32-bit loader /lib/ld-linux.so.2, and
you've presumably only installed the 64-bit loader
/lib64/ld-linux-x86-64.so.2 in the chroot.
You need to install the 32-bit runtime system in the chroot: the
loader, and all the libraries the programs need. On Debian amd64, the
32-bit loader is in the libc6-i386 package. You can install a bigger
set of 32-bit libraries by installing ia32-libs.
I bet there's a better way to verify this but i'd try to exec
ldd ./f
and search in the output which loader is needed to exec'it
man 2 execve:
ENOENT The file filename or a script or ELF interpreter does not
exist, or a shared library needed for file or interpreter can‐
not be found.
You could run ldd against this binary to look for libraries that could not be mapped and install them from multilib.