Wirebrowser is a runtime instrumentation platform built on top of the Chrome DevTools Protocol (CDP).
It provides a unified API to:
ctx.return(true)ctx.setVariable(...)ctx.followReturn()if(condition) ctx.stepOut()searchHeapSnapshot()Wirebrowser is composed of multiple subsystems:
Hook and modify JavaScript execution at runtime.
Search and analyze JavaScript objects in memory.
WB.Node.Instrumentation.addHook({file: 'auth.js', line: 10, col: 20}, {
onEnter(ctx){
ctx.log(ctx.stackTrace)
},
onLeave(ctx) {
ctx.return(true)
}
});
await WB.Node.Instrumentation.startHooks(pageId);
const results = await WB.Node.Memory.searchHeapSnapshot(pageId, {
valueSearch: [".*accessToken.*", { useRegexp: true }]
})
WB.Node.Instrumentation.addHook({file: 'auth.js', line: 10, col: 20}, {
onLeave(ctx){
ctx.followReturn()
},
onReturnFollowed(ctx, previousStep){
// override internal state
ctx.setVariable("price", 0)
}
});
await WB.Node.Instrumentation.startHooks(pageId);
WB.Node.Instrumentation.addHook({file: 'auth.js', line: 10, col: 20}, {
onLeave(ctx){
ctx.return("admin")
},
});
await WB.Node.Instrumentation.startHooks(pageId);
WB.Node.Instrumentation.addHook({file: 'auth.js', line: 10, col: 20}, {
onEnter(ctx){
if ( ctx.arguments.user !== "admin"){
ctx.stepIntoAsync()
}
},
onStep(ctx, previousStep){
if ( ctx.arguments.user !== "admin"){
ctx.stepIntoAsync()
} else {
ctx.log(previousStep.stackTrace)
}
}
});
await WB.Node.Instrumentation.startHooks(pageId);
WB.Node.Instrumentation.addHook({file: 'auth.js', line: 10, col: 20}, {
onLeave(ctx){
ctx.send({isAdmin: ctx.returnValue === 'admin' || ctx.variables.isAdmin})
}
},
async (result, logger) => {
if(result.messages?.[0]?.isAdmin){
const results = await WB.Node.Memory.searchHeapSnapshot(pageId, {
valueSearch: [".*accessToken.*", {useRegexp: true}]
})
logger.log(result)
}
);
await WB.Node.Instrumentation.startHooks(pageId);
WB.Node.Instrumentation.addHook({file: 'auth.js', line: 10, col: 20}, {
onEnter(ctx){
if(ctx.variables.isAdmin){
ctx.setVariable("isAdmin", true)
}
}
});
await WB.Node.Instrumentation.startHooks(pageId);
const results = await WB.Node.Memory.searchLiveObjects(pageId, {
valueSearch: 'authkey'
})
ctx.return() is reliable only for synchronous functionsawait may ignore overridden values(CDP / V8 limitation)
Wirebrowser is not just a debugger.
It is a runtime instrumentation layer that allows you to: