How to call methods in Frida Gadget (JavaScript API iOS)? - javascript

i have class [ClassName] and method [- setSomething].
How can i call with JS API withount Interceptor this method?

Function:
function modify_implementation(class_name, method_name, functions) {
try {
var methodObj = ObjC.classes[class_name][method_name]
var old_implementation = methodObj.implementation;
methodObj.implementation = ObjC.implement(methodObj, function () {
var args = [].slice.call(arguments); // modifying Arguments object into array
if(typeof functions['arguments'] === 'function') {
functions['arguments'](args);
}
var result = old_implementation.apply(null, args);
if(typeof functions['result'] === 'function') {
result = functions['result'](result);
}
return result;
});
} catch (err) {
console.log('[!] Error while hooking ' + class_name + ' [' + method_name + ']', err);
}
}

Related

javascript call array of functions with the same context

I am trying to create a callback functionality or at least that is how I name it. The main purpose is to call function from an array with the same context and to be able to call the next function in the array from the currently executing function.
This is the code that I have came up with:
function callCallbackChain(context, callbackChain, params) {
callbackChain.push(function () {
return true;
});
for (var i = 0, len = callbackChain.length - 1; i < len; i++) {
var cb = callbackChain[i];
var next = callbackChain[i + 1];
if (typeof cb === "function") {
cb.apply(context, [next].concat(params));
}
}
}
var callbackChain = [
function (next, foo) {
console.log('1 function call', arguments);
this.innerHTML = this.innerHTML + "function called + context:" + foo + "<br>";
next()
},
function (next, foo) {
console.log('2 function call', arguments);
this.innerHTML = this.innerHTML + "function called + context:" + foo + "<br>";
next()
},
function (next, foo) {
console.log('3 function call', arguments);
this.innerHTML = this.innerHTML + "function called + context:" + foo + "<br>";
next()
}
];
var d = document.querySelector("#conent");
callCallbackChain(d, callbackChain, ["param from the main function"]);
<div id="conent">
Initial Content
</div>
I can't seem to be able to set next function properly. It is something like a middleware.
Your next function must not actually be the next function in the chain.
Its the intent to run the next function.
function run(context, chain, params) {
var inner_run = (context, chain, params, index) => {
next = () => inner_run(context, chain, params, index + 1);
if (index < chain.length) chain[index].apply(context, [next].concat(params));
};
inner_run(context, chain, params, 0);
}
var chain = [
function (next, foo) {
this.first = true
console.log('first', arguments);
next()
},
function (next, foo) {
this.second = true
console.log('second', arguments);
// not calling next()
},
function (next, foo) {
this.third = true
console.log('third', arguments);
next()
}
];
var context = {};
run(context, chain, ["param"]);
console.log('context', context);
You need to bind it on the fly:
var nextelem=0;
function next(params...){
temp=nextelem;
nextelem++;
callbackChain[temp].bind(context)(next,...params);
}
//pass it
nextelem=1;
callbackChain[0].bind(context)(next);

Stuck between JSON nested object & Callback in Nodejs

My application calls the module to parse nested JSON object, to read values of 2 keys.
parseData(str, function (error, str) {
if (err) {
console.log("Error - parseData : ", err);
} else {
console.log(str);
}
And the parseData module is as follows
function parseData(str, callback) {
function recursiveFunction(obj) {
var keysArray = Object.keys(obj);
for (var i = 0; i < keysArray.length; i++) {
var key = keysArray[i];
var value = obj[key];
if (value === Object(value)) {
parseData(value);
} else {
if (key == 'title') {
title = value;
}
if (key == 'extract') {
var extract = value.replace(/(\r\n|\n|\r)/gm," ");
callback(null, JSON.stringify('{"title":'+ title + ', "text":' + extract));
}
}
}
}
recursiveFunction(str);
}
But it shows following error
/modules/parseData.js:22
callback(null, JSON.stringify('{"title":'+ title + ', "text":' + extract));
^
TypeError: callback is not a function
Why is callback failing ? How to return back JSON object ?
EDIT
There were some errors in the code and now corrected.
function parseData(str, callback) {
function recursiveFunction(obj) {
var keysArray = Object.keys(obj);
for (var i = 0; i < keysArray.length; i++) {
var key = keysArray[i];
var value = obj[key];
if (value === Object(value)) {
recursiveFunction(value);
} else {
if (key == 'title') {
title = value;
}
if (key == 'extract') {
var extract = value.replace(/(\r\n|\n|\r)/gm," ");
callback(null, JSON.stringify('{"title":'+ title + ', "text":' + extract));
}
}
}
}
recursiveFunction(str);
};
You're calling parseData(value); and not passing a callback; pass callback if you want that original callback to be used.

How to access the current element property name of the called function

For logging purpose, I've created a wrapper function for an element functions properties.
The wrapper function is above:
functionsWrapper: function () {
for (i = 0, args = new Array(arguments.length); i < arguments.length; i++) {
args[i] = arguments[i];
}
console.log('call for ' + arguments.callee.name + ' with params ' + argumantsLog(args));
return this['original' + arguments.callee.name].apply(this, args);
}
And then I'm using this code to wrap the element function:
logFunctionsCalls: function (element) {
if (!element)
return;
if (element.children && element.children.length)
for (var i = 0; i < element.children.length; i++)
logFunctionsCalls(element.children[i]);
if (!element.functionsLogged) {
element.functionsLogged = true;
for (var property in element) {
if (typeof element[property] != 'function')
continue;
element['original' + property] = element[property];
element[property] = functionsWrapper;
}
}
}
My problem is that the arguments.callee contains the functionsWrapper code without the property name of the called function.
You cannot use the same functionWrapper everywhere - there's no way to find out as which property it was called. Instead, created different wrappers and keep the original in closure.
for (var p in element) (function(property) {
if (typeof element[property] != 'function')
return;
var original = element[property];
element[property] = function wrapped() {
console.log('call for ' + property + ' with params ' + Array.prototype.join.call(arguments));
return original.apply(this, arguments);
};
}(p));

JavaScript DRY Object Constructors

I have an object that looks something like this:
var myObj = {
_fooCon: function(f) {
if (typeof f != 'function') throw new TypeError('Bad Foo');
this.fn = f;
},
_barCon: function(f) {
if (typeof f != 'function') throw new TypeError('Bad Bar');
this.fn = f;
},
someFoo: function(v) {
return new this._fooCon(function(x) {
return x + ' Foo ' + v;
});
},
someBar: function(v) {
return new this._barCon(function(x) {
return x + ' Bar ' + v;
});
}
};
The reason for doing this is so I can use instanceof productively (i.e., so I can distinguish between the two objects, which are used in different scenarios, despite being structurally identical). (Ignore the fact that someFoo and someBar are similar!)
Is there a way I can abstract the constructor functions, so if I need to create, say, _bazCon, I don't need to repeat myself; or, if there's a bug, I don't have to fix every constructor definition?
I tried making a factory member, like this:
_factory: function(type, f) {
if (typeof f != 'function') throw new TypeError('Bad ' + type);
this.fn = f;
}
...then:
_fooCon: function(f) { return new this._factory('Foo', f); }
Even without trying this, I can see it's not going to work! Any ideas on how to achieve what I'm looking for?
If your functions really do the same thing, then it's as simple as this:
var myObj = {
_factory: function(err) {
return function(f) {
if (typeof f != 'function') throw new TypeError('Bad ' + err);
this.fn = f;
};
},
someFoo: function(v) {
return new this._fooCon(function(x) {
return x + ' Foo ' + v;
});
},
someBar: function(v) {
return new this._barCon(function(x) {
return x + ' Bar ' + v;
});
}
};
myObj._fooCon = myObj._factory("Foo");
myObj._barCon = myObj._factory("Bar");
If there's other behavior that differentiates them, then you could have _factory receive a function argument that is invoked within the constructor. That function could use .call or .apply to set the this value to the object being constructed.
A different approach would be to use a constructor to create myObj, and take advantage of the variable scope so that you don't need to expose the _xxxCon constructors.
This uses an anonymous function as a constructor, since we don't need it again.
var myObj = new function() {
var _factory = function(err) {
return function(f) {
if (typeof f != 'function') throw new TypeError('Bad ' + err);
this.fn = f;
};
};
var _fooCon = _factory("Foo");
var _barCon = _factory("Bar");
this.someFoo = function(v) {
return new _fooCon(function(x) {
return x + ' Foo ' + v;
});
},
this.someBar = function(v) {
return new _barCon(function(x) {
return x + ' Bar ' + v;
});
}
};
You don't necessarily need the outer function to be used as a constructor, but you do need a function that returns an object to myObj.
If you did want to expose the _xxxCon functions, then change var to this., and put the this. back in someFoo and someBar.

Calling Method represented by string

I am being passed a string similar to below.
"Users_Controller.login"
"Users_Controller" represents the object below.
And "login" a method within it.
var Users_Controller = ( function () {
return{
login : function(vo, callback)
{......}
}
})();
Given only the string as a pointer,is it possible call the method?
You can use this function:
function getPropertyFromString(str, start) {
str = str.split(".");
var prop = start || window;
for (var i = 0; i < str.length; i++) {
if(prop == undefined)
return prop;
else
prop = prop[str[i]];
}
return prop;
}
getPropertyFromString("Users_Controller.login");
However, this does not allow bracket syntax.
Something like this?
var Users_Controller = (function () {
return {
login: function (name) {
alert("hello " + name);
},
logout: function (name) { alert("goodbye "+name); }
}
})();
var methods = {};
for (method in Users_Controller) {
methods["Users_Controller." + method] = Users_Controller[method];
}
methods["Users_Controller.login"]('john');
methods["Users_Controller.logout"]('john');

Categories

Resources