Multiline script in conditional break - windbg

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

Related

Getting the process ID from a crash dump file with PyKd

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 )

Ignore some locations in Windbg Conditional breakpoints

I'm trying to set a conditional hardware breakpoint on Windows Kernel-Mode in Windbg by using the following syntax :
ba w1 ffff802312345678 "j(#rip==ffff802387654321 || #rip==ffff802387654330) 'gc';''"
I used the above command in order to ignore every access to my target location (ffff802312345678) from ffff802387654321 or ffff802387654330, so everytime access from somewhere else is taken, then I would be notified.
But the problem is, it still breaks on ffff802387654321 or ffff802387654330 among the other locations.
I also read it's official documents about "Conditional Breakpoints and Register Sign Extension" and also test something like this:
ba w1 ffff802312345678 "j((#rip & 0xffffffffffffffff)=ffff802387654321 || (#rip & 0xffffffffffffffff)=ffff802387654330) 'gc';''"
But it still won't work.
So my question is:
What's wrong with the above command and how can I achieve the desired
result ?
There is no || MASM operator. It's or.
Use
ba w1 ffff802312345678 "j(#rip==ffff802387654321 or #rip==ffff802387654330) 'gc';''"
I have not reproduced your exact case, but a simpler example:
0:000> r rip
rip=0000000076db6fb0
0:000> j (#rip==0000000076db6fb0 || #rip==0) '.echo 5';'.echo 6"
Numeric expression missing from '| #rip==0) '.echo 5';'.echo 6"'
0:000> j (#rip==0000000076db6fb0 or #rip==0) '.echo 5';'.echo 6"
5

Does TASM allow a macro to be used as an operand?

I am attempting to port a macro from MASM6 to TASM5 (in IDEAL mode) and I am encountering errors. The macro itself assembles fine, but when I attempt to call it, I receive the following error during assembly:
Error xxx.asm(##) Can't use macro name in expression: M_SWAP16
The macro takes the numeric value from a text macro and performs a byte swap. The macro is generally called with ops that take immediate values or during variable initialization.
MACRO M_swap16 operand
LOCAL result
result = (((operand and 0FFh) shl 8) or ((operand and 0FF00h) shr 8))
exitm %result
ENDM
IPPROTO_TCP EQU 6
.
.
.
mov [protocol], M_swap16(IPPROTO_TCP) ; fails
.
.
.
protocol DW ?
protocol_default DW M_swap16(IPPROTO_TCP) ; fails
It works fine in MASM 6.11. Switching TASM from IDEAL to MASM mode doesn't help. Neither does moving the macro into the EQU statement. Ideas?
Unfortunately TASM5 doesn't appear to support macros returning results to expressions at least according to the last official docs. This is also what the error you are seeing is saying. More specifically, the EXITM directive doesn't take an argument like MASM can regardless of the mode you are in. However TASM's macros can still emit a line of code, so if you aren't worried about passing the expression in to the macro, I propose the following workaround (IDEAL mode):
MACRO M_swap16_EXPRESSION expr,operand
LOCAL result
result = (((operand and 0FFh) shl 8) or ((operand and 0FF00h) shr 8))
expr result
ENDM
The macro above takes an additional argument "expr" as the 1st argument which is the assembly expression you were trying to plug the original expression in. It will perform the assembly-time arithmetic on the operand and emit the final assembly line. It can be used like this:
M_swap16_EXPRESSION <mov [protocol],>,IPPROTO_TCP
...
M_swap16_EXPRESSION <protocol_default DW>,IPPROTO_TCP
I admit its ugly, but it might be the next best thing if you must use TASM.

Does windbg aliases really be expanded when a new block of code is entered?

"An alias consists of an alias name and an alias equivalent. When you use an alias name as part of a debugger command, the name is automatically replaced by the alias equivalent. This replacement occurs immediately, before the command is parsed or executed." All above is from windbg help document. The following is the content of my windbg script file.
ad /q *
;aS MyVar 0x7b;
.block
{
;aS /x ${/v:MyVar} ${MyVar}+0x1;
.block
{
.printf "MyVar1=0x%x\n",${MyVar};
.block
{
.printf "MyVar2=0x%x\n",${MyVar};
}
.printf "MyVar3=0x%x\n",${MyVar};
}
.block
{
.printf "MyVar4=0x%x\n",${MyVar};
}
}
.block
{
.printf "MyVar5=0x%x\n",${MyVar};
}
al;
The following is the result of executing this script.
0:000> $$><c:\windbg.wds
MyVar1=0x7b
MyVar2=0x7b
MyVar3=0x7b
MyVar4=0x7b
MyVar5=0x7c
Alias Value
------- -------
MyVar 0x7c
I don't know why the first four line result occured,so I come here to ask for help.
From WinDbg aS help:
Note that if the portion of the line after the semicolon requires expansion of the alias, you must enclose that second portion of the line in a new block.
From WinDbg .block help:
When each block is entered, all aliases within the block are evaluated. If you alter the value of an alias at some point within a command block, commands subsequent to that point will not use the new alias value unless they are within a subordinate block.
where subordinate obviously has the meaning of following and not nested.
So yes, you have found another limitation of WinDbg's scripting language. I recommend looking at alternatives such as PyKd or similar.

Windbg - How can I Dump Strings which match a given filter

One can dump all the string using the following command
!dumpheap -type System.string
How can dump or print only those string which starts or contains a specific "string"
Example. I am only intrested to view the string which contains "/my/app/request"
Use sosex instead of sos for this. It has a !strings command which allows you to filter strings using the /m:<filter> option.
Use !sosex.strings. See !sosex.help for options to filter strings based on content and/or length.
Not sure if !dumpheap supports that. You can always use .logopen to redirect the output to a file and post-process that. For a more elegant (and thus more complicated) solution, you can also use .shell to redirect the command output to a shell process for parsing. Here's an example:
http://blogs.msdn.com/b/baleixo/archive/2008/09/06/using-shell-to-search-text.aspx
You can also see the .shell documentation for more details:
http://msdn.microsoft.com/en-us/library/windows/hardware/ff565339(v=vs.85).aspx
If you really want to go without SOSEX, then try
.foreach (string {!dumpheap -short -type System.String}) { .foreach (search {s -u ${string}+c ${string}+c+2*poi(${string}+8) "mySearchTerm"}) { du /c80 ${string}+c }}
It uses
!dumpheap to get all Strings on .NET heap
.foreach to iterate over them
s to search for a substring
.foreach again to find out if s found something
some offset calculations to get the first character (+c) of the string and the string length (+8) (multiplied by 2 to get bytes instead of characters). Those need to be adapted in case of 64 bit applications
The /c80 is just for nicer output. You could also use !do ${string} instead of du /c80 ${string}+c if you like the .NET details of the String.