Skip to content

Commit

Permalink
Wire up some more
Browse files Browse the repository at this point in the history
  • Loading branch information
oleavr committed Oct 2, 2024
1 parent 8f2b1c8 commit e1baf2a
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 39 deletions.
2 changes: 1 addition & 1 deletion agents/tracer/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -646,7 +646,7 @@ class Agent {
private includeAbsoluteInstruction(address: NativePointer, plan: TracePlan) {
const module = plan.modules.find(address);
if (module !== null) {
plan.native.set(address.toString(), ["insn", module.name, `insn_${address.sub(module.base).toString(16)}`]);
plan.native.set(address.toString(), ["insn", module.path, `insn_${address.sub(module.base).toString(16)}`]);
} else {
plan.native.set(address.toString(), ["insn", "", `insn_${address.toString(16)}`]);
}
Expand Down
8 changes: 4 additions & 4 deletions apps/tracer/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion apps/tracer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
},
"dependencies": {
"@blueprintjs/core": "^5.12.0",
"@frida/react-use-r2": "^1.0.1",
"@frida/react-use-r2": "^1.0.2",
"@monaco-editor/react": "^4.6.0",
"monaco-editor": "^0.51.0",
"react": "^18.3.1",
Expand Down
1 change: 1 addition & 0 deletions apps/tracer/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ export default function App() {
<DisassemblyView
target={disassemblyTarget}
handlers={handlers}
onSelectTarget={setDisassemblyTarget}
onSelectHandler={setSelectedHandlerId}
onAddInstructionHook={addInstructionHook}
/>
Expand Down
106 changes: 74 additions & 32 deletions apps/tracer/src/DisassemblyView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
export interface DisassemblyViewProps {
target?: DisassemblyTarget;
handlers: Handler[];
onSelectTarget: SelectTargetRequestHandler;
onSelectHandler: SelectHandlerRequestHandler;
onAddInstructionHook: AddInstructionHookRequestHandler;
}
Expand All @@ -15,7 +16,7 @@ export type DisassemblyTarget = FunctionTarget | InstructionTarget;

export interface FunctionTarget {
type: "function";
name: string;
name?: string;
address: string;
}

Expand All @@ -24,12 +25,14 @@ export interface InstructionTarget {
address: string;
}

export type SelectTargetRequestHandler = (target: DisassemblyTarget) => void;
export type SelectHandlerRequestHandler = (id: HandlerId) => void;
export type AddInstructionHookRequestHandler = (address: bigint) => void;

export default function DisassemblyView({ target, handlers, onSelectHandler, onAddInstructionHook }: DisassemblyViewProps) {
export default function DisassemblyView({ target, handlers, onSelectTarget, onSelectHandler, onAddInstructionHook }: DisassemblyViewProps) {
const containerRef = useRef<HTMLDivElement>(null);
const [rawR2Output, setRawR2Output] = useState("");
const [_r2Ops, setR2Ops] = useState(new Map<string, R2Operation>());
const [r2Ops, setR2Ops] = useState(new Map<bigint, R2Operation>());
const [r2Output, setR2Output] = useState<string[]>([]);
const [isLoading, setIsLoading] = useState(false);
const highlightedAddressAnchorRef = useRef<HTMLAnchorElement | null>(null);
Expand All @@ -46,34 +49,37 @@ export default function DisassemblyView({ target, handlers, onSelectHandler, onA
const t = target;

async function start() {
const command = (t.type === "function")
? [
`s ${target!.address}`,
"af-",
"af",
"afn base64:" + btoa(t.name),
"pdf",
"pdfj",
].join("; ")
: `s ${t.address}; pd; pdj`;
let result = await executeR2Command(command);
const command = [
`s ${target!.address}`,
]
if (t.type === "function") {
command.push(...["af-", "af"]);
if (t.name !== undefined) {
command.push("afn base64:" + btoa(t.name));
}
command.push(...["pdf", "pdfj"]);
} else {
command.push(...["pd", "pdj"]);
}

let result = await executeR2Command(command.join(";"));
if (ignore) {
return;
}
let lines = result.trimEnd().split("\n");
if (lines[0] === "") {
if (result.startsWith("{")) {
result = await executeR2Command("pd; pdj");
lines = result.trimEnd().split("\n");
}
if (ignore) {
return;
if (ignore) {
return;
}
}

const lines = result.trimEnd().split("\n");

setRawR2Output(lines.slice(0, lines.length - 1).join("\n"));

const meta = JSON.parse(lines[lines.length - 1]);
const opItems: R2Operation[] = Array.isArray(meta) ? meta : meta.ops;
const opByAddress = new Map<string, R2Operation>(opItems.map(op => [op.offset, op]));
const opByAddress = new Map<bigint, R2Operation>(opItems.map(op => [BigInt(op.offset), op]));
setR2Ops(opByAddress);

setIsLoading(false);
Expand All @@ -100,13 +106,32 @@ export default function DisassemblyView({ target, handlers, onSelectHandler, onA
lines =
rawR2Output
.split("<br />")
.map(line => line.replace(/\b0x[0-9a-f]+\b/, address => {
const handler = handlerByAddress.get(BigInt(address));
const attrs = (handler !== undefined)
? ` class="disassembly-address-has-handler" data-handler-id="${handler.id}"`
: "";
return `<a${attrs}>${address}</a>`;
}));
.map(line => {
let address: bigint | null = null;
line = line.replace(/\b0x[0-9a-f]+\b/, rawAddress => {
address = BigInt(rawAddress);
const handler = handlerByAddress.get(address);
const attrs = (handler !== undefined)
? ` class="disassembly-address-has-handler" data-handler="${handler.id}"`
: "";
return `<a data-address="0x${address.toString(16)}" ${attrs}>${rawAddress}</a>`;
});

if (address !== null) {
const op = r2Ops.get(address);
if (op !== undefined) {
const targetAddress = op.jump;
if (targetAddress !== undefined) {
const targetLabel = op.disasm.split("&nbsp;")[1];
line = line.replace(targetLabel, _ => {
return `<a data-target="${targetAddress}" data-type="${op.type}">${targetLabel}</a>`;
});
}
}
}

return line;
});
} else {
lines = [];
}
Expand All @@ -124,7 +149,7 @@ export default function DisassemblyView({ target, handlers, onSelectHandler, onA
const unhookedAddressMenu = useMemo(() => (
<Menu>
<MenuItem
text="Add instruction-level hook here"
text="Add instruction-level hook"
icon="add"
onClick={() => {
const address = BigInt(highlightedAddressAnchorRef.current!.innerText);
Expand All @@ -140,7 +165,7 @@ export default function DisassemblyView({ target, handlers, onSelectHandler, onA
text="Go to handler"
icon="arrow-up"
onClick={() => {
const id: HandlerId = parseInt(highlightedAddressAnchorRef.current!.getAttribute("data-handler-id")!)
const id: HandlerId = parseInt(highlightedAddressAnchorRef.current!.getAttribute("data-handler")!)
onSelectHandler(id);
}}
/>
Expand All @@ -155,8 +180,23 @@ export default function DisassemblyView({ target, handlers, onSelectHandler, onA

event.preventDefault();

const branchTarget = target.getAttribute("data-target");
if (branchTarget !== null) {
const anchor = containerRef.current!.querySelector(`a[data-address="${branchTarget}"]`);
if (anchor !== null) {
anchor.scrollIntoView();
return;
}

onSelectTarget({
type: (target.getAttribute("data-type") === "call") ? "function" : "instruction",
address: branchTarget
});
return;
}

showContextMenu({
content: target.hasAttribute("data-handler-id") ? hookedAddressMenu : unhookedAddressMenu,
content: target.hasAttribute("data-handler") ? hookedAddressMenu : unhookedAddressMenu,
onClose: handleAddressMenuClose,
targetOffset: {
left: event.clientX,
Expand All @@ -175,7 +215,7 @@ export default function DisassemblyView({ target, handlers, onSelectHandler, onA
}

return (
<div className="disassembly-view" onClick={handleAddressClick}>
<div ref={containerRef} className="disassembly-view" onClick={handleAddressClick}>
{r2Output.map((line, i) => <div key={i} dangerouslySetInnerHTML={{ __html: line }} />)}
</div>
);
Expand Down Expand Up @@ -204,5 +244,7 @@ interface R2Operation {
type: string;
type_num: string;
type2_num: string;
jump?: string;
fail?: string;
reloc: boolean;
}
2 changes: 1 addition & 1 deletion apps/tracer/src/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ export function useModel() {
return () => {
ignore = true;
};
}, [selectedHandlerId, request]);
}, [selectedHandlerId, handlers, request]);

const deployCode = useCallback(async (code: string) => {
setHandlerCode(code);
Expand Down

0 comments on commit e1baf2a

Please sign in to comment.