I have the following .ts
files:
core.ts
interface Signature {
args: string[];
ret?: string;
}
const subject = 'hook'
const now = () => (new Date()).getTime()
const readable = (type: string, arg: NativePointer) => (type === 'char *' ? arg.readUtf8String() : arg)
export function hook(mod: string | null, symbol: string, signature: Signature) {
const p = Module.findExportByName(mod, symbol)
if (!p) throw new Error(`Function ${mod || 'global'}!${symbol} not found`)
const range = Process.findRangeByAddress(p)
if (!range?.protection.includes('x')) throw new Error('Invalid symbol, expected a function but received a data pointer')
const id = p.toString()
const lib = mod || Process.getModuleByAddress(p)!.name
const listener = Interceptor.attach(p, {
onEnter(args) {
const time = now()
const pretty = signature.args.map((type, i) => readable(type, args[i]))
const backtrace = Thread.backtrace(this.context, Backtracer.ACCURATE)
.map(DebugSymbol.fromAddress).filter(e => e.name)
this.backtrace = backtrace
send({
subject,
event: 'call',
args: pretty,
lib,
symbol,
backtrace,
time
})
},
onLeave(retVal) {
if (!signature.ret) return
const time = now()
const ret = readable(signature.ret, retVal)
send({
subject,
event: 'return',
lib,
symbol,
time,
backtrace: this.backtrace,
ret
})
}
})
return listener
}
sql-hooks.ts
// import { hook } from './core'
const { hook } = require('./core.ts')
ObjC.schedule(ObjC.mainQueue, function () {
enable()
});
function enable() {
console.log('enabled')
hook('libsqlite3.dylib', 'sqlite3_open', { args: ['char *', 'int'], ret: 'int' })
hook('libsqlite3.dylib', 'sqlite3_prepare_v2', { args: ['pointer', 'char *', 'int', 'pointer', 'pointer'] })
hook('libsqlite3.dylib', 'sqlite3_bind_int', { args: ['pointer', 'int', 'int'] })
hook('libsqlite3.dylib', 'sqlite3_bind_null', { args: ['pointer', 'int'] })
hook('libsqlite3.dylib', 'sqlite3_bind_text', { args: ['pointer', 'int', 'char *', 'int', 'pointer'] })
}
Then I used following command to connect these two files
frida-compile '/path/to/sql-hooks.ts' -o out.ts
Finally I used following command to actually use out.ts
frida -U -F -l '/path/to/out.ts'
But unfortunately I get this error
out.ts:1:1 - error TS1127: Invalid character.
out.ts:2:6 - error TS2304: Cannot find name 'sql'.
out.ts:2:10 - error TS2552: Cannot find name 'hooks'. Did you mean 'hook'?
out.ts:3:6 - error TS2304: Cannot find name 'sql'.
out.ts:3:10 - error TS2552: Cannot find name 'hooks'. Did you mean 'hook'?
out.ts:4:1 - error TS1127: Invalid character.
out.ts:5:11 - error TS1005: ';' expected.
out.ts:5:12 - error TS2695: Left side of comma operator is unused and has no side effects.
out.ts:5:20 - error TS1005: ';' expected.
out.ts:5:21 - error TS2695: Left side of comma operator is unused and has no side effects.
out.ts:5:48 - error TS1005: ';' expected.
out.ts:5:49 - error TS2695: Left side of comma operator is unused and has no side effects.
out.ts:5:105 - error TS1005: ';' expected.
out.ts:5:106 - error TS2695: Left side of comma operator is unused and has no side effects.
out.ts:5:130 - error TS1005: ';' expected.
out.ts:5:131 - error TS2695: Left side of comma operator is unused and has no side effects.
out.ts:5:144 - error TS1005: ';' expected.
out.ts:6:1 - error TS1127: Invalid character.
What am I doing wrong?
I bumped into a frida-compile
example (from oleavr) and I found out I was doing a couple of things wrong. In particular I took a look at the agent folder and at the package.json scripts region.
I'm going to mention two files: sql-hooks.ts
(which is my main.ts
) and core.ts
(which is my module.ts
); both of them are inside the same folder.
I changed first line of sql-hooks.ts
from
const { hook } = require('./core.ts')
to
import { hook } from './core.js'
Notice I imported core.ts
as a .js
Then I used following command to connect sql-hooks.ts
and core.ts
frida-compile '/path/to/sql-hooks.ts' -o out.js
Notice output extension is .js
And that's it, everything's gonna work fine.