Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is is actually possible to perform function evaluation in IDkmRuntimeBreakpointNotification? #61

Open
WheretIB opened this issue Jun 6, 2020 · 0 comments

Comments

@WheretIB
Copy link

WheretIB commented Jun 6, 2020

I am trying to evaluate a C++ expression with a function call when the runtime breakpoint hits, but the evaluation never completes.

In a debug monitor component, I capture the stack frame data and send it to an IDE component:

void IDkmRuntimeBreakpointNotification.OnRuntimeBreakpoint(DkmRuntimeBreakpoint runtimeBreakpoint, DkmThread thread, bool hasException, DkmEventDescriptorS eventDescriptor)
{
    var process = thread.Process;

    thread.GetCurrentFrameInfo(out ulong retAddr, out ulong frameBase, out ulong vframe);

    var data = new SupportBreakpointHitMessage
    {
        breakpointId = runtimeBreakpoint.UniqueId,
        threadId = thread.UniqueId,
        retAddr = retAddr,
        frameBase = frameBase,
        vframe = vframe
    };

    DkmCustomMessage.Create(process.Connection, process, MessageToLocal.guid, MessageToLocal.supportBreakpointHitNotification, data.Encode(), null).SendHigher();
}

in the IDE component (tested levels 1999000 and 9995000) IDkmCustomMessageCallbackReceiver.SendHigher I try to execute an expression:

const int CV_ALLREG_VFRAME = 0x00007536;
var vFrameRegister = DkmUnwoundRegister.Create(CV_ALLREG_VFRAME, new ReadOnlyCollection<byte>(BitConverter.GetBytes(data.vframe)));
var registers = thread.GetCurrentRegisters(new[] { vFrameRegister });
var instructionAddress = process.CreateNativeInstructionAddress(registers.GetInstructionPointer());
DkmStackWalkFrame frame = DkmStackWalkFrame.Create(thread, instructionAddress, data.frameBase, 0, DkmStackWalkFrameFlags.None, null, registers, null);

var inspectionSession = DkmInspectionSession.Create(process, null);

string expression = $"sethook(0x{stateAddress:x}, 0x{processData.helperHookFunctionAddress_5_1:x}, 7, 0)";

var compilerId = new DkmCompilerId(DkmVendorId.Microsoft, DkmLanguageId.Cpp);
var language = DkmLanguage.Create("C++", compilerId);
var languageExpression = DkmLanguageExpression.Create(language, DkmEvaluationFlags.None, expression, null);
var inspectionContext = DkmInspectionContext.Create(inspectionSession, frame.RuntimeInstance, thread, 2000, DkmEvaluationFlags.None, DkmFuncEvalFlags.None, 10, language, null);
var workList = DkmWorkList.Create(null);

DkmSuccessEvaluationResult result = null;

inspectionContext.EvaluateExpression(workList, languageExpression, frame, res =>
{
    if (res.ErrorCode == 0)
    {
        result = res.ResultObject as DkmSuccessEvaluationResult;

        res.ResultObject.Close();
    }
});

workList.Execute();

workList.Execute(); call never returns.
If the same evaluation is performed in a IDkmCallStackFilter.FilterNextFrame there are no issues with it.
Expressions without function evaluations can also be successfully performed with this code in IDkmCustomMessageCallbackReceiver.SendHigher.

Documentation for IDkmRuntimeBreakpointNotification.OnRuntimeBreakpoint tells that:

When this
notification is called, the target process is stopped and implementers are
able to either inspect the process or cause it to execute in a controlled
manner (slip, func-eval).

Is this really true?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant