Getting the process ID from a crash dump file with PyKd - windbg

I am analyzing a lot of crash dumps with Pykd and I would like to get the process ID (PID) from the crash dump.
In WinDbg, I'd use the command | and use my brain to figure it out. Some time later, I'd come up with a command like
.foreach /pS 3 /ps 999 ( pid {|}) {.echo ${pid}}
which extracts the process ID for me.
Just a little bit smarter and I'd use a pseudo register instead:
.printf "%p", $tpid
How would I use PyKD to get the process ID from a user mode crash dump file (.dmp)?
Of course I can always do a pykd.dbgCommand(), but I'd like to use a more robust built-in way.
I have tried
pykd.getCurrentProcessId() but it returns 0.
pykd.reg("tpid") but it says "Invalid register name"

0:000> dx Debugger.Sessions.First().Processes
Debugger.Sessions.First().Processes
[0x294c] : wait.exe
0:000> .shell -ci ".echo " type f:\src\wait\pid.py
from pykd import *
print(hex(expr("#$tpid"))).shell: Process exited
0:000> !py f:\src\wait\pid.py
0x294c
0:000> |
. 0 id: 294c examine name: F:\src\wait\wait.exe
0:000>

The pseudo reguster idea was not that bad:
pykd.expr("$tpid")
gives the process ID as a number. Format it as hexadecimal if it's needed in the same format as |.

try to use pykd.getProcessSystemID
https://githomelab.ru/pykd/pykd/-/wikis/API%20Reference#function-getprocesssystemid
getCurrentProcessId has sense if you are debugging several processes and need to switch they contexts ( like | command )

Related

Multiline script in conditional break

I'm using windbg like the following:
bp XXX!XXXX::Init ".printf \"init tid=%d, XXX=0x%x\", ##c++(#$teb->ClientId.UniqueThread), #rdx; .echo; g;"
Is there a way to avoid the \" and the one-liner here? I'm trying to be more elegant.
avoid .printf as much as you can it has certain limitation on format string length
resume from conditional breakpoint with gc (go from conditional ) instead of g (go)as you do
one alternate way to accomplish what you are doing could be like
0:000> bp 00007ff8`854ec941 "dx #$teb->ClientId.UniqueThread;r #rdx;gc"
0:000> pc
#$teb->ClientId.UniqueThread : 0x23cc [Type: void *]
rdx=0000020996d22868
00007ff8`854ec941 call fastprox!CWbemSvcWrapper::XWbemServices::WrapBSTR

Is there any equivalent command for !findstack to filter the managed code?

I found the !findstack just can be used to filter unmanaged code, however it failed to filter managed code, so is there any equivalent command for !findstack to filter the managed code ?
I don't know of a ready-to-use function like this, so I see two options here:
fiddle around with some WinDbg internal commands (which you can hardly understand half a year later)
use PyKd and write a nice script in Python
Approach a)
This may look similar to this:
~*e .foreach(word {!clrstack}) {.if ($spat("${word}", "?*RunMessageLoop?*") == 1) {.printf "Found!\n"}}
Approach b)
Put the following into a file called clrfindstack.py
from pykd import *
import sys
if len(sys.argv) == 1: # script name only
print "Please provide a search string as argument"
exit()
threads = getNumberThreads()
for thread in range(0, threads):
dbgCommand("~"+str(thread)+"s") # select the thread
stack = dbgCommand("!clrstack") # run !clrstack
if sys.argv[1] in stack: # [0] is the script name
print "Found", sys.argv[1], "in thread", thread, "(Use ~"+str(thread)+"s to select it)"
And then run it
0:000> !py c:\tmp\clrfindstack.py
Please provide a search string as argument
0:000> !py c:\tmp\clrfindstack.py RunMessageLoop
Found RunMessageLoop in thread 0 (Use ~0s to select it)
The implementation is probably not very pythonic, but does its job.

setting a breakpoint in windbg using a script

I would like to create a script in windbg that sets a breakpoint in System.Windows.Forms.Application+MarshalingControl..ctor and when that breakpoint is being hit, it just dumps the stack trace into a log file that i open.
I'm using the sos extension's !Name2EE command to get the JITTED code address, but i still don't have a way to get the exact address from what is being returned:
.block{.shell -ci "!Name2EE *!System.Windows.Forms.Application+MarshalingControl..ctor" FIND "JITTED Code Address:"}
but this returns: JITTED Code Address: 63348434
Where i would like to get only the address number itself.
Any suggestions?
Getting the jitted address
You can surround that by a .foreach which eats the words JITTED Code Address: by using /pS 3 (initial skip) and eats .shell: Process exited by /ps 3 (skip):
I tried with
0:000> .foreach /pS 3 /ps 3 (var {.shell -ci ".echo JITTED Code Address: 63348434" FIND "JITTED Code Address:"}) {.echo ${var}}
63348434
You should use
.block{.foreach /pS 3 /ps 3(var {.shell -ci "!Name2EE *!System.Windows.Forms.Application+MarshalingControl..ctor" FIND "JITTED Code Address:"}) {.echo ${var}}}
and then change .echo ${var} to whatever you like to do with the address.
Be aware of edge cases: the method may not have been jitted yet.
Managed breakpoint
I wonder a bit why you want to put a breakpoint at the jitted address and why a sosex managed breakpoint does not work for you. Have you tried !mbm and !mbp?

How to get thread IDs from a memory dump in WinDbg?

I'm trying to create a script that runs thread specific commands to output information for each thread into a separate file. Is there a way to get thread ID that I can run in the command similar to this: ~${threadId} e!clrstack.
Ultimately here is what I'm shooting for:
.foreach(tid {!threads})
{
.logopen c:\temp\${tid}.txt;
~${tid}e !dumpstack;
~${tid}e !clrstack;
~${tid}e !dso;
~${tid}e kb 200;
.logclose
}
Here is what I got so far:
.foreach /pS 1 /pS2 /pS3 /pS4 /pS5 /ps 3 (l {!runaway})
{
.printf "${l}\n";
}
The issue with this that it has the value I'm looking for with OSID. Looks like this <wantedID>:<OSID>.
How can I separate the part I need or is there an easier way to get thread ID from a memory dump?
I'm a bit confused about the use of .foreach together with ~e, because that's somehow duplicate (just the fact that you're limiting ~e to one thread doesn't result in a nested loop).
Is the command
~*e .logopen /t d:\debug\log.txt; !dumpstack; !clrstack; !dso; kb 200; .logclose
sufficient for you? The log file name will not have the thread ID.
Regarding your skip tokens of .foreach, I think you can only use /pS and /ps once. Your statement is equivalent to
.foreach /pS 5 /ps 3 (l {!runaway}) { ... }
If the thread ID really matters
It seems that the OS thread IDs are really important.
As using .foreach directly on any command like !threads, ~ or !runaway seems not flexible and reliable enough, I propose to use .shell find to get at least some consistency in output.
I'll use !teb to get the thread ID, because it is separated by a space and therefore the output of .shell find can be used as input for .foreach.
The complete command I come up with:
~*e .foreach /pS 3 /ps 20 (tid {.shell -ci "!teb" find "ClientId"}) { .logopen d:\debug\logs\log${tid}.txt; !dumpstack; !clrstack; !dso; kb 200; .logclose}
Using pykd as an extension
Using PyKd - Python extension for WinDbg, the result can be achieved like this:
Create a file tid.py, put it next to the pykd.pyd extension and give it the following content:
from pykd import *
threads = getProcessThreads()
for t in threads:
print(hex(ptrPtr(t+0x24))[2:-1])
getProcessThreads() gives you the addresses of the TEBs. At offset 0x24 you can find the thread ID. ptrPtr() reads a memory address, hex() is self-explaining, [2: removes the 0x head and :-1] removes the trailing L (don't ask me why it has a trailing L).
In WinDbg
.load pykd.pyd
!py tid.py; *** Gives one thread ID per line, nice for .foreach
.foreach (tid {!py tid.py}) { .logopen d:\debug\logs\log_${tid}.txt; ~~[${tid}]s; !dumpstack; !clrstack; !dso; kb 200; .logclose}

Using Expect with Perl and pipe to a file

I'm fairly new to Perl and have been searching the interwebs for documentation for what I'm trying to do. I'm not having any luck.
I have a program that outputs information to stdout with prompts throughout. I need to make a Perl script to pipe that information to a file.
I thought I could use Expect but there seems to be a problem with the pipe after the first prompt.
Here is the part of my code:
# Run program and compare the output to the BASE file
$cmd = "./program arg1 arg2 arg3 arg4 > $outfile";
my $exp = new Expect;
$exp->spawn($cmd);
BAIL_OUT("couldn't create expect object") if (! defined $exp);
$exp->expect(2);
$exp->send("\n");
For this case there is only a single prompt for the user to press "enter". This program is small and very fast - 2 seconds is plenty of time to reach the first prompt.
The output file only contains the first half of the information.
Does anyone have any suggestions on how I can grab the second half as well?
UPDATE:
I've verified that this works with Expect by using a simple script:
spawn ./program arg1 arg2 arg3 arg4
expect "<Return>"
send "\r"
interact
Where "< Return >" is a verbose expression that the Perl script could look for.
Note: I've tried writing my Perl script to expect "< Return >"...it makes no difference.
i.e.
$exp->expect(2, '-re', "<Return>")
Any thoughts?
UPDATE2:
Hazaah! I've found a solution to my problem...completely by accident.
So, I had a mistype in some test code I made...
$exp->expect(2);
$exp->send("\r");
$exp->expect(2);
Note the trailing expect(2)...I accidentally left that in and it worked!
So, I'm trying to understand what is happening. Unix expect does not seem work this way! It appears Expect implemented in Perl "expects" anything...not just prompts?
So, I provided expect another 2 seconds to collect stdout and I am able to get everything.
If anyone can offer some more detailed information as to what is going on here I'd love to understand what is going on.
Try sending \r instead of \n - you're trying to emulate a carriage return, not a newline, and the tty settings might not be translating them.
ALSO:
A suggestion from the Expect docs FAQ section, which seems likely given your accidental solution:
My script fails from time to time without any obvious reason. It
seems that I am sometimes loosing output from the spawned program.
You could be exiting too fast without giving the spawned program
enough time to finish. Try adding $exp->soft_close() to terminate the
program gracefully or do an expect() for 'eof'.
Alternatively, try adding a 'sleep 1' after you spawn() the program.
It could be that pty creation on your system is just slow (but this is
rather improbable if you are using the latest IO-Tty).
Standard unix/tcl expect doesn't exit in interactive mode, which could give your program enough time to finish running.
It's been a while since I've used Expect, but I'm pretty sure you need to provide something for Expect to match the prompt against:
$exp->expect( 2, 'Press enter' );
for example.