Lena is a small SDK that allows you to quickly write effective tracers for windows. Written in C++ it allows for an easy integration in existing SDK. Currently, we only support one tracer per thread.
See tests/test_lena.cpp for a quick example.
- Support more tracer (up to 4 per thread?)
- Build a C API
void lena::Init(LenaDebugger* debugger)Initialize the library. LenaInit must be called first in order to use tracing functionalities.
LenaDebugger that will be used to set and unset hardware breakpoints.
Lena uses debug registers internally to initialize its tracers. To avoid incompatibilities with external SDKs, the user must provide its own debugger managing the different hardware breakpoints himself.
struct lena::Debugger
{
// Callback handling the initialization of the hardware breakpoint.
void (*SetHardwareBreakpoint)(CONTEXT* ctx, uintptr_t address, uint32_t thread_id);
// Callback only called when the hardware breakpoint is hit.
void (*UnsetHardwareBreakpoint)(CONTEXT* context, uint32_t thread_id);
};User defined callbacks to set and unset hardware breakpoints. Hardware breakpoints are used internally to know when to start tracing.
When initializing a new tracer, LenaManager will call LenaDebugger::SetHardwareBreakpoint.
ctx: Context of the thread to set the breakpoint to.address: desired address.thread_id: thread id of the thread to set the hardware breakpoint.
When the tracer hits the first instruction to trace, LenaDebugger::UnsetHardwareBreakpoint will be called with the current context.
ctx: Context when the previously set breakpoint is set.
void lena::Cleanup()Cleanup the library.
void lena::TraceThread(uint32_t thread_id, uintptr_t from, LenaCallback callback);Thread ID of the thread you want to trace.
Address where to start tracing.
A pointer to a LenaCallback function. This will be called before every instruction when tracing.
Lena makes usage of hardware breakpoint to know when to start tracing. In order to trace every thread, it is the user responsibility to iterate through all process' threads.
int LenaCallback(CONTEXT *ctx)Callback to be executed before every instruction.
Contains the current context of the thread.
LENA_CONTINUE_TRACINGto continue tracing the current thread.LENA_STOP_TRACINGto stop tracing the current thread and reset it to its initial state.LENA_DELETE_TRACERstop tracing and delete the current tracer (thus freeing a slot)LENA_CONTINUE_SEARCHpass the exception to the next exception handler (can be useful tracing application that throwEXCEPTION_SINGLE_STEP)
Returning LENA_STOP_TRACING will not delete the tracer, but reset it. To delete your tracer after usage please the user must returns LENA_DELETE_TRACER. Not doing so might result in memory leaks as well.