Breakpoints 101
So I thought I would do something about breakpoints.. something basic and build it up to something useful.
I use notepad for all the tests and the symbols path is:
0:002> .sympath
Symbol search path is: https://msdl.microsoft.com/download/symbols
The basic commands for breakpoints are ( see the help for more detailed info on each one of these )
bp |
Set a breakpoint on an address |
bl |
List breakpoints |
bd |
Disable breakpoint(s) |
bc |
Clear breakpoints(s) |
be |
Enable breakpoint(s) |
ba |
Break on access to a specific memory address |
Here are a few examples:
Let’s set a breakpoint on CreateFileW. First we find the address via the ‘x’ command and pass the function ( we could have used wildcards in the name like createfil* )
0:002> x kernel32!createfileW
7c810760 kernel32!CreateFileW = <no type information>
0:002> bp 7c810760
Now list our current breakpoints.. note the small blue ‘e’ - means its enabled.
0:002> bl
0 e 7c810760 0001 (0001) 0:**** kernel32!CreateFileW
Now set another bp using the symbolic name
0:002> bp kernel32!createfileA
0:002> bl
0 e 7c810760 0001 (0001) 0:**** kernel32!CreateFileW
1 e 7c801a24 0001 (0001) 0:**** kernel32!CreateFileA
Disable all bp’s – see the ‘e’ has turned to ‘d’ – disabled.
0:002> bd *
0:002> bl
0 d 7c810760 0001 (0001) 0:**** kernel32!CreateFileW
1 d 7c801a24 0001 (0001) 0:**** kernel32!CreateFileA
Enable one or more – if you did a ‘be *’ it enables all – or you can do ‘be 0 1 3 5’ etc.. to enable bp’s 0,1,3 and 5
0:002> be 1
0:002> bl
0 d 7c810760 0001 (0001) 0:**** kernel32!CreateFileW
1 e 7c801a24 0001 (0001) 0:**** kernel32!CreateFileA
[ ~ Thread] bp[ID] [Options] [Address [Passes]] [ " CommandString " ]
The command tring is the interesting part here. Very useful as we will see later.
First let’s hit our breakpoint and poke around a bit.
Give the debugger a “go” via ‘g’
0:005> g
Breakpoint 0 hit
eax=0007d004 ebx=0007d004 ecx=00000003 edx=0007cd88 esi=00000000 edi=00000000
eip=7c810760 esp=0007cb14 ebp=0007cd54 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
kernel32!CreateFileW:
7c810760 8bff mov edi,edi
Show some of the stack..
0:000> kbL3
ChildEBP RetAddr Args to Child
0007cb10 77f67faf 0007d004 80000000 00000005 kernel32!CreateFileW
0007cd54 77f7a1aa 0007d004 80000000 00000005 SHLWAPI!CreateFileWrapW+0x73
0007cd8c 7ca05b66 0007d004 00000020 00000000 SHLWAPI!SHCreateStreamOnFileEx+0x48
Moving right along…..
The CreateFile function takes many parameters – but if we look at just the first one, it is a pointer to a string.
HANDLE CreateFile(
LPCTSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile
);
The stack listing via ‘kb’ only shows the first 3 parameters … we can see the rest by looking at the data relative to the base pointer or EBP.
The output below via the ‘dd’ command shows us the memory in 4 byte chunks – or DWORDS. I have highlighted the 7 parameters passed to CreateFileW
The blue is the address – so the address 0007cd54 contains 0007cd8c .
0:000> dd ebp
0007cd54 0007cd8c 77f7a1aa 0007d004 80000000
0007cd64 00000005 00000000 00000003 00000000
0007cd74 00000000 0007d004 77f7a166 000ce218
0007cd84 80000000 00000005 0007cfcc 7ca05b66
0007cd94 0007d004 00000020 00000000 00000003
0007cda4 00000000 0007cdb8 000d4238 00000000
0007cdb4 763b6eb4 00000000 0007cf2c 000000f6
0007cdc4 7c90fb3d 0007cdbc 00001c37 0007ce28
This may make it easier to see ( via the ‘dds’ command ) – remember we are dumping it in 4 byte blocks – DWORDS
0:000> dds ebp
0007cd54 0007cd8c
0007cd58 77f7a1aa SHLWAPI!SHCreateStreamOnFileEx+0x48
0007cd5c 0007d004 --> 4 bytes. 00,07,d0,04 ( remember 8 bits is a byte )
0007cd60 80000000
0007cd64 00000005
0007cd68 00000000
0007cd6c 00000003
0007cd70 00000000
0007cd74 00000000
0007cd78 0007d004
0007cd7c 77f7a166 SHLWAPI!SHCreateStreamOnFileEx
0007cd80 000ce218
0007cd84 80000000
Now each address is clearly identified and shows what is there.
0007cd5c contains 0007d004
0007cd60 contains 80000000
And so on...
You may have noticed I am using the alias ‘ebp’ and the debugger understands that as the EBP register and dumps its value.when used in general commands:
Here we display the register itself:
0:000> r ebp
ebp=0007cd54
EBP+8 in this case , is the first parameter to CreateFile – which is a pointer to the string. Let’s see if that’s true – 0007d004 should be the start of some string.
We can initially poke at it via ‘dc” – which dumps double-word values (4 bytes) and ASCII characters.
0:000> dc 0007d004
0007d004 003a0043 0044005c 0063006f 006d0075 C.:.\.D.o.c.u.m.
0007d014 006e0065 00730074 00610020 0064006e e.n.t.s. .a.n.d.
0007d024 00530020 00740065 00690074 0067006e .S.e.t.t.i.n.g.
0007d034 005c0073 00740073 00760065 005c0065 s.\.s.t.e.v.e.\.
0007d044 00650044 006b0073 006f0074 005c0070 D.e.s.k.t.o.p.\.
0007d054 006f0042 006c0069 006f0073 00740066 B.o.i.l.s.o.f.t.
0007d064 004d0020 0056004f 00430020 006e006f .M.O.V. .C.o.n.
0007d074 00650076 00740072 00720065 006c002e v.e.r.t.e.r...l.
Cool – but it’s not so friendly... let’s use ‘du’ which will dump the Unicode characters up to the null terminator
0:000> du 0007d004
0007d004 "C:\Documents and Settings\steve\"
0007d044 "Desktop\Boilsoft MOV Converter.l"
0007d084 "nk"
Much nicer – we have a regular looking string – some .lnk file.
But let’s do it all in one step – we can dereference the pointer via the ‘poi’ operator
0:000> du poi(0007cd94)
0007d004 "C:\Documents and Settings\steve\"
0007d044 "Desktop\Boilsoft MOV Converter.l"
0007d084 "nk"
Better – but what if we don’t want to hardcode the pointer? Recall that 0007cd94 is simply EBP+8 which is really the first parameter.
0:000> du poi(ebp+8)
0007d004 "C:\Documents and Settings\steve\"
0007d044 "Desktop\Boilsoft MOV Converter.l"
0007d084 "nk"
Ahh much better… so let’s bring this back to our simple breakpoint :
0:000> bl
0 e 7c810760 0001 (0001) 0:**** kernel32!CreateFileW
Let’s use that commandstring parameter I mentioned earlier – the interesting one…
A refresher from the help file shows the usage as follows:
[ ~ Thread] bp[ID] [Options] [Address [Passes]] [ " CommandString " ]
So.. we can do :
0:000> bp 7c810760 "du poi(ebp+8);g"
breakpoint 0 redefined
0:000> g
Which reads as “set a break point on address 7c810760 , and when you hit it – evaluate the command string and do what it says, which is to dump the data that ebp+8 points to as a Unicode string , and then , go.”
We give it a go – and then in notepad, click on file “save as”
0007ddd8 "C:\Documents and Settings\steve\"
0007de18 "Desktop\Shortcut to NOTES.doc.ln"
0007de58 "k"
000e1e80 "C:\Documents and Settings\steve\"
000e1ec0 "Desktop\ntoskrnl.pdb\"
000e1e80 "C:\Documents and Settings\steve\"
000e1ec0 "Desktop\ntoskrnl.pdb\"
000e1e80 "C:\Documents and Settings\steve\"
000e1ec0 "Desktop\"
000e1e80 "C:\Documents and Settings\steve\"
000e1ec0 "Desktop\"
000e1e80 "C:\Documents and Settings\steve\"
000e1ec0 ""
000e1e80 "C:\Documents and Settings\steve\"
000e1ec0 ""
000e1e80 "C:\Documents and Settings\"
000e1e80 "C:\Documents and Settings\"
000e1e80 "C:\"
00fee68c "C:\Documents and Settings\steve\"
00fee6cc "Desktop\ntoskrnl.pdb"
0007d000 "C:\Documents and Settings\All Us"
0007d040 "ers\Desktop\Far Out Field Trips."
0007d080 "lnk"
Cool – some rudimentary logging. You could fancy it up a bit and dump the stack each time as well by inserting ‘kL’ into it like
"du poi(ebp+8);kL;g"
And you get something like :
0007d000 "C:\Documents and Settings\All Us"
0007d040 "ers\Desktop\Camtasia Studio 2.ln"
0007d080 "k"
ChildEBP RetAddr
0007cb0c 77f67faf kernel32!CreateFileW
0007cd50 77f7a1aa SHLWAPI!CreateFileWrapW+0x73
0007cd88 7ca05b66 SHLWAPI!SHCreateStreamOnFileEx+0x48
0007cfc8 7ca05b17 SHELL32!CShellLink::_LoadFromFile+0x4c
0007cfd4 7c9fd574 SHELL32!CShellLink::Load+0x1e
0007d20c 7c9fd847 SHELL32!CFSFolder::_HandlerCreateInstance+0x7e
0007d4c4 7c9efc8e SHELL32!CFSFolder::_LoadHandler+0xcf
0007d4f4 7ca34d8a SHELL32!CFSFolder::GetUIObjectOf+0x261
0007d51c 7ca34d56 SHELL32!CDesktopFolder::_GetItemUIObject+0x31
0007d54c 7ca2d1b6 SHELL32!CDesktopFolder::GetUIObjectOf+0x110
0007d588 763dad01 SHELL32!CRegFolder::GetUIObjectOf+0x28c
0007d5c0 763b9df3 comdlg32!CFileOpenBrowser::ResolveLink+0x34
0007d5d8 763b4a21 comdlg32!CFileOpenBrowser::GetLinkStatus+0x26
0007d80c 763b4999 comdlg32!CFileOpenBrowser::LinkMatchSpec+0x55
0007d828 7c9f7dd1 comdlg32!CFileOpenBrowser::IncludeObject+0xd2
0007d83c 7c9f7d87 SHELL32!CDefView::_IncludeObject+0x49
0007d888 7c9f7c2b SHELL32!CDefView::_AddObject+0x19
0007d8b0 7c9f7bab SHELL32!CDefviewEnumTask::_FilterDPAs+0xdc
0007d8d0 7c9f7e2e SHELL32!CDefviewEnumTask::FillObjectsDoneToView+0xbd
0007d8e8 7c9f763e SHELL32!CDefView::FillDone+0x57
0007d000 "C:\Documents and Settings\All Us"
0007d040 "ers\Desktop\Far Out Field Trips."
0007d080 "lnk"
ChildEBP RetAddr
0007cb0c 77f67faf kernel32!CreateFileW
0007cd50 77f7a1aa SHLWAPI!CreateFileWrapW+0x73
0007cd88 7ca05b66 SHLWAPI!SHCreateStreamOnFileEx+0x48
0007cfc8 7ca05b17 SHELL32!CShellLink::_LoadFromFile+0x4c
0007cfd4 7c9fd574 SHELL32!CShellLink::Load+0x1e
0007d20c 7c9fd847 SHELL32!CFSFolder::_HandlerCreateInstance+0x7e
0007d4c4 7c9efc8e SHELL32!CFSFolder::_LoadHandler+0xcf
0007d4f4 7ca34d8a SHELL32!CFSFolder::GetUIObjectOf+0x261
0007d51c 7ca34d56 SHELL32!CDesktopFolder::_GetItemUIObject+0x31
0007d54c 7ca2d1b6 SHELL32!CDesktopFolder::GetUIObjectOf+0x110
0007d588 763dad01 SHELL32!CRegFolder::GetUIObjectOf+0x28c
0007d5c0 763b9df3 comdlg32!CFileOpenBrowser::ResolveLink+0x34
0007d5d8 763b4a21 comdlg32!CFileOpenBrowser::GetLinkStatus+0x26
0007d80c 763b4999 comdlg32!CFileOpenBrowser::LinkMatchSpec+0x55
0007d828 7c9f7dd1 comdlg32!CFileOpenBrowser::IncludeObject+0xd2
0007d83c 7c9f7d87 SHELL32!CDefView::_IncludeObject+0x49
0007d888 7c9f7c2b SHELL32!CDefView::_AddObject+0x19
0007d8b0 7c9f7bab SHELL32!CDefviewEnumTask::_FilterDPAs+0xdc
0007d8d0 7c9f7e2e SHELL32!CDefviewEnumTask::FillObjectsDoneToView+0xbd
0007d8e8 7c9f763e SHELL32!CDefView::FillDone+0x57
Anyway – next time we will move on to some more interesting uses for breakpoints..
Spatdsg