c00000fd
c00000fd

Reputation: 22289

How to get notified of changes in target from my WinDbg extension - or, how does ChangeDebuggeeState work?

I need to be able to receive a notification from my WinDbg extension when the target's virtual or physical memory changes via DEBUG_DATA_SPACE_VIRTUAL or DEBUG_DATA_SPACE_PHYSICAL flags.

I was hoping to use ChangeDebuggeeState callback for that.

I wrote my own class MyCallbacks, that implements IDebugEventCallbacksWide interface. I then used it in SetEventCallbacksWide from the DebugExtensionInitialize callback, as such:

CComPtr<IDebugControl4> pDebugControl;
DebugCreate(IID_PPV(pDebugControl));

CComPtr<IDebugClient5> pDbgClient;
pDebugControl->QueryInterface(IID_PPV(pDbgClient));

MyCallbacks* pC = new MyCallbacks;
pDbgClient->SetEventCallbacksWide(pC);

The AddRef method of my MyCallbacks class is called after the sequence above, as well as the GetInterestMask, where I specify what exactly I want to trap:

HRESULT STDMETHODCALLTYPE MyCallbacks::GetInterestMask(
        _Out_ PULONG Mask
        )
{
    *Mask = DEBUG_EVENT_CHANGE_DEBUGGEE_STATE;

    return S_OK;
}

But then when I work with WinDbg by stepping through the live target, my implemented ChangeDebuggeeState function is never called. Where I would expect it to be called since the target's virtual/physical memory is being changed.

Any idea what am I doing wrong?

PS. I tried adjusting it a little bit, and used the DEBUG_EVENT_BREAKPOINT mask for GetInterestMask and then checked if my IDebugEventCallbacksWide::Breakpoint method was called when a kernel breakpoint was hit in the WinDbg - and my callback was never called either.

Upvotes: 0

Views: 71

Answers (1)

blabb
blabb

Reputation: 9007

just dusted up a very pretty old code and dumped it here

the code for ChangeDebugeeState looks like this

STDMETHODIMP EventCallbacks::ChangeDebuggeeState(THIS_ IN ULONG Flags, IN ULONG64 Argument)
{
       printf("ChangeDebugeeState Flags = %x\n", Flags);
       if ((Flags & DEBUG_CDS_ALL) == DEBUG_CDS_ALL)
       {
              printf("Flags = DEBUG_CDS_ALL\n");
       }
       else if ((Flags & DEBUG_CDS_REGISTERS) == DEBUG_CDS_REGISTERS)
       {
              printf("Flags = DEBUG_CDS_REGISTERS\n");
       }
       else if ((Flags & DEBUG_CDS_DATA) == DEBUG_CDS_DATA)
       {
              printf("Flags = DEBUG_CDS_DATA\n");
              if ((Argument & DEBUG_DATA_SPACE_VIRTUAL) == DEBUG_DATA_SPACE_VIRTUAL)
              {
                     printf("virtual Data Change\n");
              }
              else
              {
                     printf("some other data Change\n");
              }
       }
       else if ((Flags & DEBUG_CDS_REFRESH) == DEBUG_CDS_REFRESH)
       {
              {
                     printf("Flags = DEBUG_CDS_REFRESH\n");
              }
       }
       else
       {
              printf("unknown flags\n");
       }
       printf("ChangeDebugeeState Argument  = %I64x\n", Argument);
       State = 1;
       return DEBUG_STATUS_NO_CHANGE;
}

and on editing the virtual memory the callbacks gets hit like this

0:000>dd [rsp+8] l1
000000b2`5c2ff820  00000000
ChangeDebugeeState Flags = 4
Flags = DEBUG_CDS_REFRESH
ChangeDebugeeState Argument  = 2
testdump!__scrt_common_main_seh:
00007ff6`576e11f0 48895c2408      mov     qword ptr [rsp+8],rbx ss:000000b2`5c2ff820=0000000000000000
0:000>ed [rsp+8]             <<<<<<<<<<<<<<<<<<<<<<
000000b2`5c2ff820 00000000 2345  <<<<<<<<<<<< changing virtual memory contents
ChangeDebugeeState Flags = 2
Flags = DEBUG_CDS_DATA
virtual Data Change
ChangeDebugeeState Argument  = 0
000000b2`5c2ff824 00000000
ChangeDebugeeState Flags = 4
Flags = DEBUG_CDS_REFRESH
ChangeDebugeeState Argument  = 2
testdump!__scrt_common_main_seh:
00007ff6`576e11f0 48895c2408      mov     qword ptr [rsp+8],rbx ss:000000b2`5c2ff820=0000000000002345
0:000>

hope you can adapt it to your needs
be aware it is a stand alone utility not an extension dll
you may need to fine tune it

the breakpoint callback on setting a bp at Sleep() and continuing result as follows

0:000>bp KERNELBASE!Sleep
ChangeDebugeeState Flags = 4
Flags = DEBUG_CDS_REFRESH
ChangeDebugeeState Argument  = 2
testdump!__scrt_common_main [inlined in testdump!mainCRTStartup+0x4]:
00007ff6`43711400 e89f040000      call    testdump!__security_init_cookie
0:000>g
ChangeEngineState Flags = 10
ChangeEngineState Argument  = 1
ChangeDebugeeState Flags = 4
Flags = DEBUG_CDS_REFRESH
ChangeDebugeeState Argument  = 2
ChangeEngineState Flags = 10
ChangeEngineState Argument  = 1
this is a src for test dump
ChangeDebugeeState Flags = 1
Flags = DEBUG_CDS_REGISTERS
ChangeDebugeeState Argument  = 10
Breakpoint 1 hit
ChangeEngineState Flags = 10
ChangeEngineState Argument  = 100000006
ChangeEngineState Flags = 1
ChangeEngineState Argument  = 0
ChangeDebugeeState Flags = ffffffff
Flags = DEBUG_CDS_ALL
ChangeDebugeeState Argument  = 0
Bpcallback bp 0000022A85612E20  <<<<<<<<<<<<<<< spew from callback
ChangeEngineState Flags = 10
ChangeEngineState Argument  = 6
ChangeSymbolState Flags = 4
ChangeSymbolState Argument  = 0
KERNELBASE!Sleep:
00007ffd`3ddcb440 33d2            xor     edx,edx

Upvotes: 1

Related Questions