I've been trying to hit a breakpoint inside a function only if a string in a nested struct as an argument matches a specific pattern of my choosing, like so:
bp `main.c:2236` ".block { .if ( $spat(\"@@(stNames->NameComponent.Buffer)\", \"*ab*\" )){.echo \"BKP HIT! \"; .printf \"%mu str\n\",> @@(NameInfo->FinalComponent.Buffer); } .else {.echo \"NO HIT \"; .printf \"%mu str:\n\", @@(stNames->NameComponent.Buffer); gc;} } "
This breakpoint is set right at the beginning of the function, after the parameter symbols have already been resolved. It's acting weird, sometimes it gets hit all the time even if the pattern in $spat doesn't match, and sometimes it doesn't hit even if the pattern matches.
I also tried this with no luck, as I can't find a way to use the poi() command in that case of a nested struct. Snippet bellow:
bp Kernel32!CreateFileW ".printf \"%mu\\n\", poi(esp+4); as /mu ${/v:FileName} poi(esp+4); .block{.if $spat(\"${FileName}\", \"*target*\") {.echo Hit} .else {.echo Not Yet;g;}}"
In WinDbg, you can create a conditional breakpoint by clicking Breakpoints from the Edit menu, entering a new breakpoint address into the Command box, and entering a condition into the Condition box.
Conditional breakpoints allow you to break inside a code block when a defined expression evaluates to true. Conditional breakpoints highlight as orange instead of blue. Add a conditional breakpoint by right clicking a line number, selecting Add Conditional Breakpoint , and entering an expression.
First, set a breakpoint at a given location. Then, use the context menu on the breakpoint in the left editor margin or in the Breakpoints view in the Debug perspective, and select the breakpoint’s properties. In the dialog box, check Enable Condition, and enter an arbitrary Java condition, such as list.
Right-click the breakpoint symbol and select Conditions (or press Alt + F9, C). Or hover over the breakpoint symbol, select the Settings icon, and then select Conditions in the Breakpoint Settings window.
the expression \"@@(stNames->NameComponent.Buffer)\"
probably does not evaluate to a quoted string
evaluate independently
when writing conditionals break down the conditionals as small as possible
and put them down in a txt file and provide the script file to the break point
like bp
:32" $$>a< c:\\windscrypted.txt
it is much easier to comperhend
also it would be helpful to provide a correct answer if the question has independently reproducible content
since i cannot evaluate the incomprehensible expression in the question i have provided a demo below see if this is what is asked
Helper to Compile and Link
structnest:\>type "c:\Program Files\Microsoft Visual Studio 10.0\VC\compile.bat"
@ECHO OFF
REM Compile and Link Helper Utility.
REM Add New Entry CompileMe in Visual_Studio_IDE->Tools->ExternalTools.
REM Provide path to this bat file in command
REM Provide $(ItemFileName)$(ItemExt) as Arguments
REM $(BinDir) as Initial Directory
REM Enjoy One Click Compile & link Simple Single File Demo Sources
@call "C:\Program Files\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" x86
cl /Zi /nologo /W4 /analyze %1% /link /RELEASE
pause
The Source File Details
structnest:\>dir /b
structnest.cpp
structnest:\>type structnest.cpp
#include <windows.h>
#include <winternl.h>
#include <stdio.h>
#define SOMESIZE 20
typedef VOID (NTAPI *g_RtlInitUnicodeString) (PUNICODE_STRING DestinationStri
ng, PCWSTR SourceString );
#pragma pack (1)
typedef struct _OUTNEST
{
int a;
int b;
short c;
UNICODE_STRING Nestin;
}OutNest,*POutNest;
#pragma pack()
int main (void)
{
POutNest MyNest = ( POutNest ) calloc ( 0x01 , sizeof(OutNest) );
PWSTR buff = ( PWSTR ) calloc ( 0x30 , sizeof(wchar_t) );
HMODULE hMod = LoadLibrary("ntdll.dll");
if ( (hMod != NULL) && (MyNest != NULL) && (buff != NULL))
{
g_RtlInitUnicodeString RtlInitUnicodeString = ( g_RtlInitUnicodeString )
GetProcAddress ( hMod , "RtlInitUnicodeString");
if (RtlInitUnicodeString != NULL )
{
for (int i = 0; i< SOMESIZE; i++)
{
swprintf_s(buff, 0x29 , L"this is string number %.2d",i);
RtlInitUnicodeString(&MyNest->Nestin,buff);
printf("%S\n",MyNest->Nestin.Buffer);
}
printf("done\n");
goto getout;
}
printf("GetprocAddress failed\n");
goto getout;
}
printf("calloc() %p %p LoadLib %p failed\n" , MyNest,buff,hMod);
getout:
if (MyNest)
free(MyNest);
if(buff)
free(buff);
if(hMod)
FreeLibrary(hMod);
return 0;
}
structnest:\>"c:\Program Files\Microsoft Visual Studio 10.0\VC\compile.bat" stru
ctnest.cpp
Setting environment for using Microsoft Visual Studio 2010 x86 tools.
structnest.cpp
Press any key to continue . . .
structnest:\>dir /b *.exe
structnest.exe
structnest:\>structnest.exe
this is string number 00
this is string number 01
this is string number 02
this is string number 03
this is string number 04
this is string number 05
this is string number 06
this is string number 07
this is string number 08
this is string number 09
this is string number 10
this is string number 11
this is string number 12
this is string number 13
this is string number 14
this is string number 15
this is string number 16
this is string number 17
this is string number 18
this is string number 19
done
The Script File Details
structnest:\>type c:\nestedbreak.txt
as /mu ${/v:mystr} @@( MyNest->Nestin.Buffer );
.block { r $t0 = $spat( "${mystr}", "*11" ); }
.if( @$t0 != 1 ) { gc } ;
explanation of script file
as /mu ${/v:mystr}
Sets the alias equivalent equal to the null-terminated Unicode string
that begins at Address @@( MyNest->Nestin.Buffer ).
.block {} to force alias evaluation.
a Pseudo register $t0 is set to the result of $spat() can be 0 or 1
"${mystr}" on alias evaluation will become "this is string number 00"
a Double Quoted string not address or some other expression
"*11" is again a Double Quoted wild card pattern string it will match "11"
at any position in the Input String .
.if is a conditinal that will break only when @$t0 == 1
now that we have a slightly more comprehensibe condition where each of the expression is independently verifible we procedd with using it in a break point
Execution Details
structnest:\>cdb -c ".lines;g main;r;.echo SET A CONDITINAL BREAK POINT AND RUN
THE EXE;bp `:32` \" $$^>a^< c:\\nestedbreak.txt \";g ;.lastevent;.echo why did w
e break here ? now that we broke lets go again;g;q " structnest.exe
explanation as follows
cdb.exe console mode windbg;
.lines; load line information (lineinfo default off in cdb.exe needed to set bp on src lines)
g main; ( we are interested in our code for which we have src not some random system module)
r; print the registers to confirm we reached main properly
.echo just a signal to show that we are alive and kicking
`:32` "$$>a< c:\\nestedbreak.txt" conditional break point on src line 32 ( inner double quotes/ unaccpetable > < chars escaped )
g; run the exe
.lastevent; shows the reason why we broke;
.echo a signal to indicate that we broke
g;q; finish running the exe and quit debugger
Execution Output Details
structnest:\>cdb -c ".lines;g main;r;.echo SET A CONDITINAL BREAK POINT AND RUN
THE EXE;bp `:32` \" $$^>a^< c:\\nestedbreak.txt \";g ;.lastevent;.echo why did w
e break here ? now that we broke lets go again;g;q " structnest.exe
Microsoft (R) Windows Debugger Version 6.12.0002.633 X86
0:000> cdb: Reading initial command '.lines;g main;r;.echo SET A CONDITINAL BREA
K POINT AND RUN THE EXE;bp `:32` " $$>a< c:\\nestedbreak.txt ";g ;.lastevent;.ec
ho why did we break here ? now that we broke lets go again;g;q '
Line number information will be loaded
eax=00034180 ebx=7ffd6000 ecx=00000001 edx=0041a5f0 esi=00000000 edi=00000000
eip=00401000 esp=0013ff7c ebp=0013ffc0 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
structnest!main:
00401000 55 push ebp
SET A CONDITINAL BREAK POINT AND RUN THE EXE
this is string number 00
this is string number 01
this is string number 02
this is string number 03
this is string number 04
this is string number 05
this is string number 06
this is string number 07
this is string number 08
this is string number 09
this is string number 10
Last event: 16d0.2784: Hit breakpoint 0
debugger time: Thu May 15 16:10:10.625 2014 (UTC + 5:30)
why did we break here ? now that we broke lets go again
this is string number 11
this is string number 12
this is string number 13
this is string number 14
this is string number 15
this is string number 16
this is string number 17
this is string number 18
this is string number 19
done
quit:
structnest:\>
You can use python extension for windbg. It allows to set conditional breakpoint with python callback.
kd>!pycmd
>>>myApp = module("MyApp.exe")
>>>setBp( myApp.Func1, lambda : getParam("var2").filed3 > 10 )
>>>quit()
kd>g
You can see: 1) myApp.Func1 - pykd finds offsets by symbolic information 2) getParam("var2") - pykd finds function parameters 3) getParam("var2").filed3 - it is easy to work with structures
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With