How to pass to Frida a .ts file which depends on another .ts - frida

I have 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.

Related

How to get a value from SecretString returned from AwsCustomResource (service: 'SecretsManager', action: 'getSecretValue') as plain text?

I'm modifying the code from this workshop to do cross-account rather than cross-region.
https://cdk-advanced.workshop.aws/start.html
The first thing I did was install and configure cdk-assume-role-credential-plugin and bootstrapped.
In the workshop they use a AwsCustomResource to get around the cross-region limitation of StringParameter.valueFromLookup.
static valueFromLookup(scope, parameterName) Requires that the stack this scope is defined in will have explicit account/region information. Otherwise, it will fail during synthesis.Using an AwsCustomResource allows them to override the region from stack.
const targetKeyLookupCR = new cr.AwsCustomResource(this, 'TargetKeyLookup', {
onUpdate: { // will also be called for a CREATE event
service: 'SSM',
action: 'getParameter',
parameters: {
Name: props.targetKeyIdSsmParameterName
},
region: props.targetRegion,
physicalResourceId: cr.PhysicalResourceId.of(Date.now().toString())
},
policy: cr.AwsCustomResourcePolicy.fromSdkCalls({resources: [parameterArn]})
});
Unfortunately you cannot override account of stack in a similar fashion. Adding an assumedRole does not help either. It always looks for parameter in stack's account.
I tried to use SecretsManager & AwsCustomResource to get around that cross-account limitation:
const targetKeyLookupCR = new cr.AwsCustomResource(this, 'TargetKeyLookup', {
onUpdate: {
service: 'SecretsManager',
action: 'getSecretValue',
parameters: {
SecretId: props.targetKeyIdSsmParameterName
},
assumedRoleArn: 'arn:aws:iam::111111111111:role/MultiRegionS3CrrKmsCmkXacct',
region: props.targetRegion,
physicalResourceId: cr.PhysicalResourceId.of(Date.now().toString())
},
policy: cr.AwsCustomResourcePolicy.fromSdkCalls({resources: [parameterArn]})
});
const secretString = targetKeyLookupCR.getResponseField(dataPath);
The code above returns a string that looks like this.
"{"password":"/];asdf(5;{ASDF=L%UuVxasDFHg`(:l","MyKeyID":"arn:aws:kms:us-west-1: 111111111111:key/1111a22b-3c44-5ddd-66e7-f8f9999a1111"}"
I can see it in CloudWatch:
2021-08-14T04:34:15.641Z c5ae47f7-1e4a-43a3-a475-d0d16ea7e1be INFO Responding {"Status":"SUCCESS","Reason":"OK",...
"SecretString":"{"password":"/];asdf(5;{ASDF=L%UuVxasDFHg`(:l","MyKeyID":"arn:aws:kms:us-west-1: 111111111111:key/1111a22b-3c44-5ddd-66e7-f8f9999a1111}"...}
In the workshop they use the response directly:
role.addToPolicy(new iam.PolicyStatement({
resources: [targetKeyLookupCR.getResponseField('Parameter.Value')],
actions: ['kms:Encrypt'] }));
To get the Value of MyKeyID, I've tried...
JSON.parse and splitting the string. No matter what I try ends up with an error like 'Unexpected token $ in JSON at position 0' or 'TypeError: Cannot read property 'split' of undefined'
This led me to https://docs.aws.amazon.com/cdk/latest/guide/tokens.html#tokens_json, which I definitely thought was going to be the answer! It was not. More 'Unexpected token $ in JSON at position 0' errors.
const stack = cdk.Stack.of(this);
const secretString = targetKeyLookupCR.getResponseField('SecretString');
const jsonString = stack.toJsonString(secretString);
const jsonObj = JSON.parse(jsonString);
Update:
From this https://docs.aws.amazon.com/cdk/api/latest/docs/core-readme.html#cfnjson I got a different error that indicates it has the right string, but just can't parse it properly. Unexpected token p in JSON at position 3 at JSON.parse ().
const secretString = targetKeyLookupCR.getResponseField('SecretString');
const cfnJson = new CfnJson(this, 'cfn-json', {
value: secretString,
});
// #ts-ignore
const myKeyId = cfnJson.MyKeyID || '*';
This is because CfnJson adds quotes around string:
"Value": {
"Fn::Join": [
"",
[
"\"",
{
"Fn::GetAtt": [
"MySourceTargetKeyLookupACF65EAE",
"SecretString"
]
},
"\""
]
]
}
I'm not sure how to proceed. How would I get the ARN from secretString as plain text?
I guess I was looking for a more elegant solution, but this works...
const secretString = targetKeyLookupCR.getResponseField('SecretString');
const myKeyId = cdk.Fn.select(7,cdk.Fn.split('"', secretString));
It splits the secretString into an array using double quote as delimiter
cdk.Fn.split('"', secretString)
and selects the 7th item from array produced by split
cdk.Fn.select(7, <array>)

Enum initializer as const

Are vala enums not integer based? This example generates a "c" compile error. Not a big deal, but would like to understand why.
const int INT_UNINITIALIZED = 999;
public enum ScopeTypes {
/*OSS:Fix:GLib requires a default value, set GLOBALS = 0
(VSCodeDbgSvr.exe:31979): GLib-GObject-CRITICAL **: g_param_spec_enum: assertion 'g_enum_get_value (enum_class, default_value) != NULL' failed*/
NONE = INT_UNINITIALIZED,
GLOBALS = 0,
ARGUMENTS,
LOCALS,
EXCEPTIONS,
TOT_SCOPE_TYPES;
//Vala enums may have methods:
public bool is_global() {
return (this == GLOBALS || this == EXCEPTIONS);
}
public bool is_function() {
return (this == ARGUMENTS || this == LOCALS);
}
public bool is_valid() {
return (this != NONE);
}
}
The compile output:
> Executing task: /opt/vala/bin/valac helloworld.vala class1.vala --pkg libvala-0.40 -X -I/opt/vala/include/vala-0.40 -X -O0 --vapidir=/opt/vala/share/vala/vapi --debug --save-temps -o helloworld.exe <
/media/george/SharedData/Projects/Vala/Examples/playground-2/helloworld.c:82:21: error: ‘INT_UNINITIALIZED’ undeclared here (not in a function)
SCOPE_TYPES_NONE = INT_UNINITIALIZED,
^~~~~~~~~~~~~~~~~
error: cc exited with status 256
Compilation failed: 1 error(s), 1 warning(s)
The terminal process terminated with exit code: 1
The relevant part of the error message is:
error: ‘INT_UNINITIALIZED’ undeclared here (not in a function)
The C compiler is complaining that it can not find the declaration of your constant. So it is not a type problem at all.
It is a scope / ordering problem.
If you compile the code with valac -C you get a .c file that looks something like this:
typedef enum {
SCOPE_TYPES_NONE = INT_UNINITIALIZED,
SCOPE_TYPES_GLOBALS = 0,
SCOPE_TYPES_ARGUMENTS,
SCOPE_TYPES_LOCALS,
SCOPE_TYPES_EXCEPTIONS,
SCOPE_TYPES_TOT_SCOPE_TYPES
} ScopeTypes;
#define INT_UNINITIALIZED 999
Note how the Vala compiler has reordered the code to declare the enum first and the constant later.
Since in C the order of declarations in a file is important this can not compile.
I would consider this to be a compiler bug and you may want to report this to the GNOME bugtracker (product Vala).

How to use translation in global validation with redux-form validation

When trying to use validation in a global validator with this code:
errors.fieldMissing = [translate('aor.validation.fieldMissing')];
I get the following error:
Warning: Failed prop type: Invalid prop `errorText` supplied to `TextField`, expected a ReactNode.
Without the translation(), just setting the error to an array of a string, everything works as expected.
How can translation() be used in global validation?
For example(edited from AOR example posts):
<SimpleForm defaultValue={{ average_note: 0 }} validate={(values, props) => {
const errors = {};
['title', 'teaser'].forEach((field) => {
if (!values[field]) {
errors[field] = [props.translate('aor.validation.required')];
}
});
...
A short example of translate hoc and translate props:
import { translate as translator } from 'admin-on-rest';
const Title = translator(({ record, translate }) => <span>{record ? translate('title.product', { name: record.name }) : ''}</span>);

solcover fail to generate test coverage with my simple add contract

I want to use solcover to generate test coverage of my contract.
https://github.com/JoinColony/solcover
I test it with the simple one:
contract Add {
function Add() {
}
function sum(uint x, uint y) returns (uint) {
return (x+y);
}
}
And here is my test code:
contract('Add', function(accounts) {
it("should return 5 when add 2 and 3", function() {
var add = Add.deployed();
return add.sum.call(2,3).then(function(res){
assert.equal(res.valueOf(), 5, "add result is 5");
});
});
});
But there are some errs when compile it.
Add.sol:2:1: Warning: Source file does not specify required compiler version!Consider adding "pragma solidity ^0.4.6
contract Add {
^
Spanning multiple lines.
Compilation failed. See above.
fs.js:549
Then i add compile version like this:
pragma solidity ^0.4.6;
contract Add {
function Add() {
}
function sum(uint x, uint y) returns (uint) {
return (x+y);
}
}
And now it pass the compile. But this time I got the error:
cp: no such file or directory: ./../originalContracts/Migrations.sol
rm: no such file or directory: ./allFiredEvents
Compiling Add.sol...
Contract: Add
✓ should return 5 when add 2 and 3
1 passing (15s)
fs.js:549
return binding.open(pathModule._makeLong(path), stringToFlags(flags), mode);
^
Error: ENOENT: no such file or directory, open './allFiredEvents'
at Error (native)
at Object.fs.openSync (fs.js:549:18)
at Object.fs.readFileSync (fs.js:397:15)
at Object.<anonymous> (/Users/maiffany/graduate/mytest/solcover/runCoveredTests.js:60:13)
at Module._compile (module.js:409:26)
at Object.Module._extensions..js (module.js:416:10)
at Module.load (module.js:343:32)
at Function.Module._load (module.js:300:12)
at Function.Module.runMain (module.js:441:10)
at startup (node.js:139:18)
And in the runCoveredTests.js I found this:
55:shell.cp("./../originalContracts/Migrations.sol",./../contracts/Migrations.sol");
56:
57:shell.rm('./allFiredEvents'); //Delete previous results
58:shell.exec('truffle test --network coverage');
59:
60:events = fs.readFileSync('./allFiredEvents').toString().split('\n')
I guess maybe it is this command that generate file "allFiredEvents". So i try this in my command line:
truffle test --network coverage
Compiling Add.sol...
Contract: Add
✓ should return 5 when add 2 and 3
1 passing (24s)
But i still can't find the file "allFiredEvents".
So where did i get wrong?

JSLint 2 - How can I ignore multiple function parameters

In JSLint 2, unparam is gone. Insteady, you may name a function parameter 'ignore' and the linter will ignore its unused state.
The problem I can't solve: How do I ignore multiple function parameters? Here's what I'm looking to replace:
$rootScope.$on('$routeChangeError', function (ignore_ev, ignore_current, ignore_previous, rejection) {
if (rejection === 'route value is not an integer') {
useTheUnloved(ignore_ev);
useTheUnloved(ignore_current);
useTheUnloved(ignore_previous);
$location.path(ENV.uiRouteBase + '/');
}
});
useTheUnloved = function (ignore) {
return 'JSLint 2 - how can I ignore multiple function args';
};

Resources