Checking instanceof in node.js addons using Nan - javascript

I am trying to verify that an object passed to a node addon is of the correct type before I unwrap it and start to use it. Here's the solution that I've cobbled together from looking at various sources on the web.
Persistent data:
Nan::Persistent<v8::Function> Event::constructor;
Nan::Persistent<v8::FunctionTemplate> Event::tpl;
The Init function:
void Event::Init(v8::Local<v8::Object> exports) {
Nan::HandleScope scope;
// Prepare constructor template
v8::Local<v8::FunctionTemplate> ctor = Nan::New<v8::FunctionTemplate>(Event::New);
ctor->InstanceTemplate()->SetInternalFieldCount(1);
ctor->SetClassName(Nan::New("Event").ToLocalChecked());
// create a template for checking instances
Local<FunctionTemplate> localTemplate = Nan::New<FunctionTemplate>(Event::New);
localTemplate->SetClassName(Nan::New("Event").ToLocalChecked());
tpl.Reset(localTemplate);
// Statics
Nan::SetMethod(ctor, "x", Event::X);
// Prototype
Nan::SetPrototypeMethod(ctor, "addInfo", Event::addInfo);
Nan::SetPrototypeMethod(ctor, "toString", Event::toString);
constructor.Reset(ctor->GetFunction());
Nan::Set(exports, Nan::New("Event").ToLocalChecked(), ctor->GetFunction());
}
And where I attempt to use it:
if (Nan::New(tpl)->HasInstance(info[0])) {
message = "it is an Event instance";
}
The problem is that the HasInstance() never returns true.
The JavaScript code is basically
let e = new Event()
fn(e) // where fn performs the HasInstance() test.

There is no need to make a second FunctionTemplate. The one you've set on the exports (ctor) is the one that gets used when you call new Event() in JS, while the second one (localTemplate) gets saved to Event::tpl and is the one from which the HasInstance() call gets made. They're different FunctionTemplates, so the HasInstance() call returns false.
Instead of this:
...
Local<FunctionTemplate> localTemplate = Nan::New<FunctionTemplate>(Event::New);
localTemplate->SetClassName(Nan::New("Event").ToLocalChecked());
tpl.Reset(localTemplate);
...
just try this:
...
tpl.Reset(ctor);
...

Related

get a variable value from a method at runtime with frida

I'm completely beginner to frida.
I've this final method which belongs to class say X.
I want to extract the value of token variable -> result.getToken() when i hook frida to the android app which contains that class at runtime.
can anyone complete this code with javascript API of frida to get the value of token variable ?
Java.perform(function () {
Java.choose("com.xx.xx", {
onMatch: function (inst) {
//.................................
}
});
console.log("Done");
});
then i'll use --> frida -U -f "xxx.apk" -l test.js
thank you so much for help !!
Java.choose is in most cases the wrong approach because that only lists the existing instances of a class, so you can only hook a method if there is already an instance loaded into memory.
The common way is to hook the method itself so that all existing and newly created instances use your hook.
var classInstanceIdResult = Java.use('com.google.firebase.iid.InstanceIdResult');
var getTokenMethod = classInstanceIdResult.getToken.overload();
// replace the getToken() method with out own implementation
getTokenMethod.implementation = function () {
// call the orignal method
var ret = getTokenMethod.call(this);
// do something with ret
console.log("Token: " + ret);
return ret;
}
BTW: The code for hooking a Java method can simply be generated by using Jadx-Gui. Just decompile the APK, select the method and let Jadx generate the Frida code snipped necessary to hook the method (see context menu of the method).

Disabling console access for specific Javascript files

In my current project with lots of dependencies I need a way to disable console access for specific libraries so that those files can't use any of the console functionality.
I could of course disable console functionality by simply finding and replacing it in the library bundle, but as this project has a lot of dependencies that would make updating libraries a huge hassle.
I'm aware that I can disable console functionality by overwriting it with an empty function block:
console.log = function(){};
But that disables the console functionality for the entire project. So im looking for an implementation, or a line of code with which I can disable console functionality for a specific file or code block.
Write a white-listing "middleware" for console.log
// Preserve the old console.log
const log = console.log;
// Used a dictionary because it's faster than lists for lookups
const whiteListedFunctions = {"hello": true};
// Whitelisting "middleware". We used the function's name "funcName"
// as a criteria, but it's adaptable
const isWhitelisted = callerData => callerData.funcName in whiteListedFunctions;
// Replacing the default "console.log"
console.log = arg => {
const stack = new Error().stack.split("at")[2].trim().split(' ');
const fileParts = stack[1].substr(1, stack[1].length - 2).split(':');
const callerData = {
funcName: stack[0],
file: fileParts.slice(0, fileParts.length - 2).join(':'),
lineColNumber: fileParts.slice(fileParts.length - 2).join(':')
};
if (isWhitelisted(callerData)) { // Filtering happens here
log(arg);
}
};
// Define the calling functions
function hello() { console.log("hello"); }
function world() { console.log("world"); }
hello(); // => Prints hello
world(); // => Doesn't print anything
Method explanation
You can do this by creating a whitelist (or blacklist) that will contain your filtering criteria. For example it may contain the name of the functions that call console.log or maybe the file name, or even the line and column numbers.
After that you create your whitelisting "middleware". This will take the caller function data and decide if it can log stuff or not. This will be done based on the previously defined whitelist. You can choose your preferred criteria in this "middleware".
Then you actually replace console.log by overriding with your new logger. This logger will take as an argument the message to log (maybe multiple arguments?). In this function you also need to find the data relating to the caller function (which wanted to call console.log).
Once you have the caller data, you can then use your whitelisting middleware to decide if it can log stuff
Getting information about the caller function
This part is a little "hacky" (but it got the job done in this case). We basically create an Error and check its stack attribute like this new Error().stack. Which will give us this trace
Error
at console.log.arg [as log] (https://stacksnippets.net/js:25:7)
at hello (https://stacksnippets.net/js:41:11)
at https://stacksnippets.net/js:48:1
After processing (split, map, etc...) the trace we get the caller function data. For example here we have
The caller function's name: hello
The file name: https://stacksnippets.net/js
The line and column number: 41:11 (watch out for minifiers)
This bit was inspired by VLAZ's answer in How to disable console.log messages based on criteria from specific javascript source (method, file) or message contents, so make sure to check it out. Really good and thorough post.
Note
To make sense of the trace we can do new Error().stack.split("at")[INDEX].trim().split(' ') where INDEX is the position of the function call you want to target in the stack trace. So if you want to get a different "level" that the one used in this example, try changing INDEX
Just redefine the console to log over a condition, your condition of course will be a check over which library is accessing the function:
// Your condition, could be anything
let condition = true;
/* Redefine the console object changing only the log function with your new version and keeping all the other functionalities intact
*/
let console = (old => ({
...old,
log: text => { if (condition) old.log(text) }
}))(window.console)
// Redefine the old console
window.console = console;
console.log('hello!')
Hope it helped :)
Yes, you can disable console logs from files based on their path! Here's a solution:
// in ./loud-lib.js
module.exports = {
logsSomething: () => console.log('hello from loud-lib')
}
// in ./silent-lib.js
module.exports = {
logsSomething: () => console.log('hello from silent-lib')
}
// in ./index.js
const loud = require('./loud-lib');
const silent = require('./silent-lib');
// save console.log
const log = console.log;
// redefinition of console.log
console.log = (...params) => {
// define regexp for path of libraries that log too much
const loudLibs = [/loud-lib/];
// check if the paths logged in the stacktract match with at least one regexp
const tooLoud = !!loudLibs.find(reg => reg.test(new Error().stack));
// log only if the log is coming from a library that doesn't logs too much
if (!tooLoud) log(...params);
};
loud.logsSomething();
silent.logsSomething();
$ node ./index.js
hello from silent-lib
This is based on the fact that new Error() produces a stack trace that identifies from which file is the error coming from (recursively).
Based on this observation, you can define an array of regular expression that match the name of libraries you don't want to hear logs from. You can get really specific and creative with the re-definition of console.log, but I kept it simple.
However, be aware of this (especially when using Webpack): if you bundle all your JS assets into one single bundle.js, the stacktrace will always point to bundle.js, thus logging everything. You'll have to go further from my code, for example by using stack-source-map, but I don't have sufficient details on your project to deliver a solution. I hope the ideas above are sufficient for you.

JavaScript Revealing Module pattern private variable state

I have recently started working on a JavaScript project and coming from Java world things seem, not surprisingly, weird at times.
I was implementing a simple module (Using revealing module pattern, afaik) which would provide config based on initialisation but notice that after a "local" variable domain is assigned in init() function its value differs depending whether it is accessed via a "getter" function getDomain() or directly via domain variable as exposed via modules "public" API.
See the following stripped down code which demonstrates the issue.
var ConfigManager = (function() {
var privateDomain = 'default';
function init(dom) {
privateDomain = dom;
}
function getDomain() {
return privateDomain;
}
return {
init: init,
domain: privateDomain,
getDomain: getDomain
};
})();
console.log(ConfigManager.domain); // Prints 'default'
console.log(ConfigManager.getDomain()); // Prints 'default'
ConfigManager.init('new domain');
console.log(ConfigManager.domain); // Prints 'default' <-- What??
console.log(ConfigManager.getDomain()); // Prints 'new domain'
At this point I am very confused how a variable returned from a getter function can have a different value when it is accessed directly?
Than you in advance!
Since privateDomain is a String, you're not copying / returning the reference, but the value.
Therefore when you're changing the domain using the init function, it just updates privateDomain, since domain has no link to it other than being a copy.
Hope it helps! :)
It's because when domain is returned, it's value is still "default". It's how Javascript works, more info here: Javascript by reference vs. by value
But when you use the function "getDomain" you will get the updated value.
Also have a look at the get/set syntax: Getter

Destructure function arguments, pass by reference and execution order in javascript/coffeescript [duplicate]

I'm running into an odd issue with a Backbone.js Model where an array member is being shown as blank. It looks something like this:
var Session = Backbone.Model.extend({
defaults: {
// ...
widgets: []
},
addWidget: function (widget) {
var widgets = this.get("widgets");
widgets.push(widget);
this.trigger("change:widgets", this, widgets);
},
// ...
// I have a method on the model to grabbing a member of the array
getWidget: function (id) {
console.log(this.attributes);
console.log(this.attributes.widgets);
// ...
}
});
I then add a widget via addWidget. When trying getWidget the result I get (in Chrome) is this:
Object
widgets: Array[1]
0: child
length: 1
__proto__: Array[0]
__proto__: Object
[]
It's showing that widgets is not empty when logging this.attributes but it's shown as empty when logging this.attributes.widgets. Does anyone know what would cause this?
EDIT
I've changed the model to instantiate the widgets array in the initialization method to avoid references across multiple instances, and I started using backbone-nested with no luck.
Be careful about trusting the console, there is often asynchronous behavior that can trip you up.
You're expecting console.log(x) to behave like this:
You call console.log(x).
x is dumped to the console.
Execution continues on with the statement immediately following your console.log(x) call.
But that's not what happens, the reality is more like this:
You call console.log(x).
The browser grabs a reference to x, and queues up the "real" console.log call for later.
Various other bits of JavaScript run (or not).
Later, the console.log call from (2) gets around to dumping the current state of x into the console but this x won't necessarily match the x as it was in (2).
In your case, you're doing this:
console.log(this.attributes);
console.log(this.attributes.widgets);
So you have something like this at (2):
attributes.widgets
^ ^
| |
console.log -+ |
console.log -----------+
and then something is happening in (3) which effectively does this.attributes.widgets = [...] (i.e. changes the attributes.widget reference) and so, when (4) comes around, you have this:
attributes.widgets // the new one from (3)
^
|
console.log -+
console.log -----------> widgets // the original from (1)
This leaves you seeing two different versions of widgets: the new one which received something in (3) and the original which is empty.
When you do this:
console.log(_(this.attributes).clone());
console.log(_(this.attributes.widgets).clone());
you're grabbing copies of this.attributes and this.attributes.widgets that are attached to the console.log calls so (3) won't interfere with your references and you see sensible results in the console.
That's the answer to this:
It's showing that widgets is not empty when logging this.attributes but it's shown as empty when logging this.attributes.widgets. Does anyone know what would cause this?
As far as the underlying problem goes, you probably have a fetch call somewhere and you're not taking its asynchronous behavior into account. The solution is probably to bind to an "add" or "reset" event.
Remember that [] in JS is just an alias to new Array(), and since objects are passed by reference, every instance of your Session model will share the same array object. This leads to all kinds of problems, including arrays appearing to be empty.
To make this work the way you want, you need to initialize your widgets array in the constructor. This will create a unique widget array for each Session object, and should alleviate your problem:
var Session = Backbone.Model.extend({
defaults: {
// ...
widgets: false
},
initialize: function(){
this.set('widgets',[]);
},
addWidget: function (widget) {
var widgets = this.get("widgets");
widgets.push(widget);
this.trigger("change:widgets", this, widgets);
},
// ...
// I have a method on the model to grabbing a member of the array
getWidget: function (id) {
console.log(this.attributes);
console.log(this.attributes.widgets);
// ...
}
});
Tested in a fiddle with Chrome and Firefox: http://jsfiddle.net/imsky/XBKYZ/
var s = new Session;
s.addWidget({"name":"test"});
s.getWidget()
Console output:
Object
widgets: Array[1]
__proto__: Object
[
Object
name: "test"
__proto__: Object
]

JavaScript Factory class throws errors if function name is not a 'constructed string'

I have a Factory class that I use in JavaScript to dynamically load a class file over AJAX and then return an object. I have run into a VERY peculiar bug in the system though that throws errors in EVERY browser, but under a condition that is beyond my ability to explain.
Here is a simplified version of my Factory class (I removed a lot of type checking and error handling to cut it down to bare minimum).
function Factory(){
// This holds which files have already been loaded
var loaded=new Object();
// Returns a new object
this.getObject=function(className,methodName,methodData){
if(loadFile('class.'+className+'.js')){
// Making sure that the object name is defined
if(window[className]!=null){
// Has to be an object
if(typeof(window[className])=='function'){
// Creating a temporary object
return new window[className];
}
}
}
}
// Loads a file over AJAX
var loadFile=function(address){
// Loads as long as the file has not already been loaded
if(loaded[address]==null){
// Required for AJAX connections (without ASYNC)
var XMLHttp=new XMLHttpRequest();
XMLHttp.open('GET',address,false);
XMLHttp.send(null);
// Result based on response status
if(XMLHttp.status===200 || XMLHttp.status===304){
// Getting the contents of the script
var data=XMLHttp.responseText;
// Loading the script contents to the browser
(window.execScript || function(data){
window['eval'].call(window,data);
})(data);
// makes sure that file is loaded only once
loaded[address]=true;
}
}
}
This is what the user does:
var Factory=new Factory();
var alpha=Factory.getObject('example');
alpha.set(32);
alpha.get();
var beta=Factory.getObject('example');
beta.set(64);
alpha.get();
beta.get();
This fails, it says 'object is not a function' when the function is run for the second time (at the return new window[className]; line). I understand if I am missing something here, BUT here's the kicker:
If I prefix className in my window[] calls, then it works. For example, if I change my 'example' class filename to 'test_example' and then have these lines:
... if(window['test_'+className]!=null){ ...
... if(typeof(window['test_'+className])=='function'){ ...
... return new window['test_'+className]; ...
Then it works and both alpha and beta objects work as expected. When I refer to them purely through a variable, they fail. I tried things like className.toString() without success and even this fails:
className+''
This is really weird, I don't know where to look and what to try out anymore, does anyone know why this happens?
EDIT: Here is an example of the 'example.js' script that is being loaded:
function example(){
var myVar=16;
this.set=function(value){
myVar=value;
}
this.get=function(){
alert(myVar);
}
}
(and if I rename this to test_example() and load the functions as shown above with constructed strings, then it again works)
I figured out where the error was, which my above, cut-down version does not show. Apparently I named my new variable the same that the name of the class itself was, thus after first initialization it got overwritten.

Categories

Resources