r2papi
Version:
r2api on top of r2pipe for typescript and js
503 lines (502 loc) • 15.4 kB
TypeScript
import { R2Shell } from "./shell.js";
import { R2PipeSync } from "./r2pipe.js";
export type InstructionType = "mov" | "jmp" | "cmp" | "nop" | "call" | "add" | "sub";
export type InstructionFamily = "cpu" | "fpu" | "priv";
export type GraphFormat = "dot" | "json" | "mermaid" | "ascii";
export type Permission = "---" | "r--" | "rw-" | "rwx" | "r-x" | "-wx" | "--x";
export type R2Papi = R2PapiSync;
export interface SearchResult {
offset: number;
type: string;
data: string;
}
export interface DebugModule {
base: string;
name: string;
path: string;
size: number;
}
export interface Flag {
name: string;
size: number;
offset: number;
}
export type PluginFamily = "anal" | "arch" | "bin" | "core" | "crypto" | "debug" | "egg" | "esil" | "fs" | "io" | "lang";
export interface ThreadContext {
context: any;
id: number;
state: string;
selected: boolean;
}
export interface CallRef {
addr: number;
type: string;
at: number;
}
export interface FunctionDetails {
offset: number;
name: string;
size: number;
noreturn: boolean;
stackframe: number;
ebbs: number;
signature: string;
nbbs: number;
callrefs: CallRef[];
codexrefs: CallRef[];
}
export interface BinFile {
arch: string;
static: boolean;
va: boolean;
stripped: boolean;
pic: boolean;
relocs: boolean;
sanitize: boolean;
baddr: number;
binsz: number;
bintype: string;
bits: number;
canary: boolean;
class: string;
compiler: string;
endian: string;
machine: string;
nx: boolean;
os: string;
laddr: number;
linenum: boolean;
havecode: boolean;
intrp: string;
}
export interface Reference {
from: number;
type: string;
perm: string;
opcode: string;
fcn_addr: number;
fcn_name: string;
realname: string;
refname: string;
}
export interface BasicBlock {
addr: number;
size: number;
jump: number;
fail: number;
opaddr: number;
inputs: number;
outputs: number;
ninstr: number;
instrs: number[];
traced: boolean;
}
export declare class ThreadClass {
api: any;
constructor(r2: any);
backtrace(): string;
sleep(seconds: number): string;
}
export interface Instruction {
type: InstructionType;
addr: number;
opcode: string;
pseudo: string;
mnemonic: string;
sign: boolean;
family: InstructionFamily;
description: string;
esil: string;
opex: any;
size: number;
ptr: number;
bytes: string;
id: number;
refptr: number;
direction: "read" | "write";
stackptr: number;
stack: string;
}
export declare class ModuleClass {
api: any;
constructor(r2: R2PipeSync);
fileName(): string;
name(): string;
findBaseAddress(): string;
getBaseAddress(name: string): string;
getExportByName(name: string): NativePointer;
findExportByName(name: string): NativePointer;
enumerateExports(): any;
enumerateImports(): any;
enumerateSymbols(): any;
enumerateEntrypoints(): any;
enumerateRanges(): any;
}
export declare class ProcessClass {
r2: any;
constructor(r2: R2PipeSync);
enumerateMallocRanges(): void;
enumerateSystemRanges(): void;
enumerateRanges(): void;
enumerateThreads(): any;
enumerateModules(): any;
getModuleByAddress(addr: NativePointer | number | string): any;
getModuleByName(moduleName: string): any;
codeSigningPolicy(): string;
getTmpDir(): any;
getHomeDir(): any;
platform(): any;
getCurrentDir(): any;
getCurrentThreadId(): number;
pageSize(): number;
isDebuggerAttached(): boolean;
setExceptionHandler(): void;
id(): any;
pointerSize(): number;
}
/**
* Assembler and disassembler facilities to decode and encode instructions
*
* @typedef Assembler
*/
export declare class Assembler {
program: string;
labels: any;
endian: boolean;
pc: NativePointer;
r2: R2PipeSync;
constructor(myr2?: R2PipeSync);
/**
* Change the address of the program counter, some instructions need to know where
* are they located before being encoded or decoded.
*
* @param {NativePointerValue}
*/
setProgramCounter(pc: NativePointer): void;
setEndian(big: boolean): void;
toString(): string;
append(x: string): void;
label(s: string): NativePointer;
/**
* Encode (assemble) an instruction by taking the string representation.
*
* @param {string} the string representation of the instruction to assemble
* @returns {string} the hexpairs that represent the assembled instruciton
*/
encode(s: string): string;
/**
* Decode (disassemble) an instruction by taking the hexpairs string as input.
* TODO: should take an array of bytes too
*
* @param {string} the hexadecimal pairs of bytes to decode as an instruction
* @returns {string} the mnemonic and operands of the resulting decoding
*/
decode(s: string): string;
}
/**
* High level abstraction on top of the r2 command interface provided by r2pipe.
*
* @typedef R2Papi
*/
export declare class R2PapiSync {
/**
* Keep a reference r2pipe instance
*
* @type {R2PipeSync}
*/
r2: R2PipeSync;
/**
* Create a new instance of the R2Papi class, taking an r2pipe interface as reference.
*
* @param {R2PipeSync} the r2pipe instance to use as backend.
* @returns {R2Papi} instance
*/
constructor(r2: R2PipeSync);
toString(): string;
toJSON(): string;
/**
* Get the base address used by the current loaded binary
*
* @returns {NativePointer} address of the base of the binary
*/
getBaseAddress(): NativePointer;
jsonToTypescript(name: string, a: any): string;
/**
* Get the general purpose register size of the targize architecture in bits
*
* @returns {number} the regsize
*/
getBits(): number;
/**
* Get the name of the arch plugin selected, which tends to be the same target architecture.
* Note that on some situations, this info will be stored protected bby the AirForce.
* When using the r2ghidra arch plugin the underlying arch is in `asm.cpu`:
*
* @returns {string} the name of the target architecture.
*/
getArch(): string;
callTrim(x: string): string;
cmdTrim(x: string): string;
/**
* Get the name of the selected CPU for the current selected architecture.
*
* @returns {string} the value of asm.cpu
*/
getCpu(): string;
setArch(arch: string, bits: number | undefined): void;
setFlagSpace(name: string): void;
demangleSymbol(lang: string, mangledName: string): string;
setLogLevel(level: number): void;
/**
* should return the id for the new map using the given file descriptor
*/
newMap(fd: number, vaddr: NativePointer, size: number, paddr: NativePointer, perm: Permission, name?: string): void;
at(a: string): NativePointer;
getShell(): R2Shell;
version(): string;
platform(): string;
arch(): string;
bits(): string;
id(): number;
printAt(msg: string, x: number, y: number): void;
clearScreen(): R2Papi;
getConfig(key: string): Error | string;
setConfig(key: string, val: string): R2Papi;
getRegisterStateForEsil(): string;
getRegisters(): any;
resizeFile(newSize: number): R2Papi;
insertNullBytes(newSize: number, at?: NativePointer | number | string): R2Papi;
removeBytes(newSize: number, at?: NativePointer | number | string): R2Papi;
seek(addr: number): R2Papi;
currentSeek(): NativePointer;
seekToRelativeOpcode(nth: number): NativePointer;
getBlockSize(): number;
setBlockSize(a: number): R2Papi;
countFlags(): number;
countFunctions(): number;
analyzeFunctionsWithEsil(depth?: number): void;
analyzeProgramWithEsil(depth?: number): void;
analyzeProgram(depth?: number): this;
enumerateThreads(): ThreadContext[];
currentThreadId(): number;
setRegisters(obj: any): void;
hex(s: number | string): string;
step(): R2Papi;
stepOver(): R2Papi;
math(expr: number | string): number;
stepUntil(dst: NativePointer | string | number): void;
enumerateXrefsTo(s: string): string[];
findXrefsTo(s: string, use_esil: boolean): void;
analyzeFunctionsFromCalls(): R2Papi;
autonameAllFunctions(): R2Papi;
analyzeFunctionsWithPreludes(): R2Papi;
analyzeObjCReferences(): R2Papi;
analyzeImports(): R2Papi;
searchDisasm(s: string): SearchResult[];
searchString(s: string): SearchResult[];
searchBytes(data: number[]): SearchResult[];
binInfo(): BinFile;
selectBinary(id: number): void;
openFile(name: string): number | Error;
openFileNomap(name: string): number | Error;
currentFile(name: string): string;
enumeratePlugins(type: PluginFamily): any;
enumerateModules(): DebugModule[];
enumerateFiles(): any;
enumerateBinaries(): any;
enumerateMaps(): any;
enumerateClasses(): any;
enumerateSymbols(): any;
enumerateExports(): any;
enumerateImports(): any;
enumerateLibraries(): string[];
enumerateSections(): any;
enumerateSegments(): any;
enumerateEntrypoints(): any;
enumerateRelocations(): any;
enumerateFunctions(): FunctionDetails[];
enumerateFlags(): Flag[];
skip(): void;
ptr(s: string | number): NativePointer;
call(s: string): string;
callj(s: string): any;
cmd(s: string): string;
cmdj(s: string): any;
log(s: string): void;
clippy(msg: string): void;
ascii(msg: string): void;
}
export declare class NativeFunction {
constructor();
}
export declare class NativeCallback {
constructor();
}
/**
* Global function that returns a new instance of a NativePointer.
* Saves some typing: `ptr(0)` is the same as `new NativePointer(0)`
*
* @type function
*/
export declare function ptr(v: NativePointerValue): NativePointer;
/**
* A NativePointer can be described using a string that contains a number in any base (hexadecimal and decimal are the most common formats used)
* But it actually supports anything else that could be handled by radare2. You can use symbol names, math operations or special symbols like `$$`.
*
* @type NativePointerValue
*/
export type NativePointerValue = string | number | NativePointer;
/**
* Class providing a way to work with 64bit pointers from Javascript, this API mimics the same
* well-known promitive available in Frida, but it's baked by the current session of r2.
*
* It is also possible to use this class via the global `ptr` function.
*
* @typedef NativePointer
*/
export declare class NativePointer {
addr: string;
api: R2Papi;
constructor(s: NativePointerValue, api?: R2Papi);
/**
* Filter a string to be used as a valid flag name
*
* @param {string} name of the symbol name
* @returns {string} filtered name to be used as a flag
*/
filterFlag(name: string): string;
/**
* Set a flag (name) at the offset pointed
*
* @param {string} name of the flag to set
* @returns {string} base64 decoded string
*/
setFlag(name: string): void;
/**
* Remove the flag in the current offset
*
*/
unsetFlag(): void;
/**
* Render an hexadecimal dump of the bytes contained in the range starting
* in the current pointer and given length.
*
* @param {number} length optional amount of bytes to dump, using blocksize
* @returns {string} string containing the hexadecimal dump of memory
*/
hexdump(length?: number): string;
functionGraph(format?: GraphFormat): string;
readByteArray(len: number): number[];
readHexString(len: number): string;
and(a: number): NativePointer;
or(a: number): NativePointer;
add(a: number): NativePointer;
sub(a: number): NativePointer;
writeByteArray(data: number[]): NativePointer;
writeAssembly(instruction: string): NativePointer;
writeCString(s: string): NativePointer;
writeWideString(s: string): NativePointer;
/**
* Check if it's a pointer to the address zero. Also known as null pointer.
*
* @returns {boolean} true if null
*/
isNull(): boolean;
/**
* Compare current pointer with the passed one, and return -1, 0 or 1.
*
* * if (this < arg) return -1;
* * if (this > arg) return 1;
* * if (this == arg) return 0;
*
* @returns {number} returns -1, 0 or 1 depending on the comparison of the pointers
*/
compare(a: NativePointerValue): number;
/**
* Check if it's a pointer to the address zero. Also known as null pointer.
*
* @returns {boolean} true if null
*/
pointsToNull(): boolean;
toJSON(): string;
toString(): string;
toNumber(): number;
writePointer(p: NativePointer): void;
readRelativePointer(): NativePointer;
readPointer(): NativePointer;
readS8(): number;
readU8(): number;
readU16(): number;
readU16le(): number;
readU16be(): number;
readS16(): number;
readS16le(): number;
readS16be(): number;
readS32(): number;
readU32(): number;
readU32le(): number;
readU32be(): number;
readU64(): number;
readU64le(): number;
readU64be(): number;
writeInt(n: number): boolean;
/**
* Write a byte in the current offset, the value must be between 0 and 255
*
* @param {string} n number to write in the pointed byte in the current address
* @returns {boolean} false if the operation failed
*/
writeU8(n: number): boolean;
writeU16(n: number): boolean;
writeU16be(n: number): boolean;
writeU16le(n: number): boolean;
writeU32(n: number): boolean;
writeU32be(n: number): boolean;
writeU32le(n: number): boolean;
writeU64(n: number): boolean;
writeU64be(n: number): boolean;
writeU64le(n: number): boolean;
readInt32(): number;
readCString(): string;
readWideString(): string;
readPascalString(): string;
instruction(): Instruction;
disassemble(length?: number): string;
analyzeFunction(): NativePointer;
analyzeFunctionRecursively(): NativePointer;
name(): string;
methodName(): string;
symbolName(): string;
getFunction(): FunctionDetails;
basicBlock(): BasicBlock;
functionBasicBlocks(): BasicBlock[];
xrefs(): Reference[];
}
/**
* Global instance of R2Papi based on the current session of radare2.
* Note that `r2` is the global instance of `r2pipe` used by `R`.
*
* @type R2Papi
*/
export declare const R: R2Papi;
/**
* Global instance of the Module class based on the current radare2 session.
* This variable mimics the same APIs shipped by Frida.
*
* @type ModuleClass
*/
export declare const Module: ModuleClass;
/**
* Global instance of the Process class based on the current radare2 session.
* This variable mimics the same APIs shipped by Frida.
*
* @type ProcessClass
*/
export declare const Process: ProcessClass;
/**
* Global instance of the Thread class based on the current radare2 session.
* This variable mimics the same APIs shipped by Frida.
*
* @type ThreadClass
*/
export declare const Thread: ThreadClass;