Print stacktrace using Frida - frida

I'm able to sucessfully hook into an Android method using Frida, but I am trying to find out who is calling that method. I can find that out if I can rewrite the method with Frida to print the stacktrace when the method gets called. I've tried a few things, but all of them have had some sort of error. This is the latest thing I have tried.
setImmediate(function() {
console.log("[*] Starting script");
Java.perform(function () {
var Activity = Java.use("com.package.MyClass");
Activity.getUpdates.overload('boolean', 'java.lang.String', 'java.lang.String').implementation = function (v1, v2, v3) {
console.log("v1: " + v1);
console.log("v2: " + v2);
console.log("v3: " + v3);
Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Exception").$new())
};
});
})
This is resulting in the following error
Error: Not allowed outside Java.perform() callback
at d (frida/node_modules/frida-java/index.js:86)
at frida/node_modules/frida-java/index.js:366
at [anon] (repl1.js:11)
at input:1
Any idea how I can achieve this?

I fixed it by using this:
Java.perform(function() {
console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Exception").$new()))
});
It is necessary to add an additional Java.perform call

Related

Twilio Video - switch media devices option not working

I am using twilio with twilio-video v beta-2 counting on the master branch of this repohttps://github.com/twilio/video-quickstart-js
I got to display the select media and push the devices into it but when I am trying to updateVideoDevice I got an error
updateVideoDevice error TypeError: track must be a LocalAudioTrack, LocalVideoTrack, LocalDataTrack, or MediaStreamTrack
at Object.INVALID_TYPE (index.js:30952)
at Object.validateLocalTrack (index.js:31469)
at LocalParticipant.unpublishTrack (index.js:17047)
at index.js:17096
at Array.reduce (<anonymous>)
at LocalParticipant.unpublishTracks (index.js:17095)
at index.js:36056
my updateVideoDevice function is as the following
function updateVideoDevice(event) {
const select = event.target;
const localParticipant = room.localParticipant;
if (select.value !== '') {
Video.createLocalVideoTrack({
deviceId: { exact: select.value }
}).then(function(localVideoTrack) {
const tracks = Array.from(localParticipant.videoTracks.values());
localParticipant.unpublishTracks(tracks);
log(localParticipant.identity + " removed track: " + tracks[0].kind);
detachTracks(tracks);
localParticipant.publishTrack(localVideoTrack);
log(localParticipant.identity + " added track: " + localVideoTrack.kind);
const previewContainer = document.getElementById('local-media');
attachTracks([localVideoTrack], previewContainer);
})
.catch(error => {
console.error('updateVideoDevice error' ,error);
});
}
}
can any one explain what I am doing wrong?
Twilio developer evangelist here.
This looks to be a breaking change between Twilio Video JS v1 and v2. In the v2 documentation, calling localParticipant.videoTracks returns a Map of <Track.SID, LocalVideoTrackPublication>. Calling .values() on that map returns an iterator of LocalVideoTrackPublications which is then turned to an array using Array.from.
The issue is that you then pass that array of LocalVideoTrackPublications to localParticipant.unpublishTracks(tracks); which causes the error because unpublishTracks expects an array of LocalTracks not LocalVideoTrackPublications.
You could fix this by mapping over the publications and returning the track property:
const tracks = Array.from(localParticipant.videoTracks.values())
.map(publication => publication.track);
Let me know if that helps.

SignalR Clients.Caller(Clients.Caller.GroupName) does not work

I am going through tutorials on SignalR and cannot figure out why this does not work.
This works:
Clients.Group("TestGroup").displayText(person.Name, person.Message);
This does not work:
Clients.Group(Clients.Caller.GroupName).displayText(person.Name, person.Message);
The javascript code:
var broadcaster = $.connection.groupHub;
broadcaster.client.displayText = function (name, message) {
$('#messages').append('<li>' + name + ' said:' + message + '</li>');
};
$.connection.hub.start().done(function () {
$('#broadcast').off().on("click", function () {
var group = "GroupTest";
broadcaster.server.join(group);
broadcaster.state.GroupName = group;
broadcaster.server.broadcastMessage({ Name: $('#name').val(), Message: $('#message').val() });
broadcaster.server.leave(group);
});
This doesn't make a lot of sense to me and its probably something small I am missing or doing wrong.
The problem is solved by casting to string:
Clients.Group(Clients.Caller.GroupName).displayText(person.Name, person.Message);
should be:
Clients.Group((string)Clients.Caller.GroupName).displayText(person.Name, person.Message);
I assume this is because the Clients.Caller and broadcast.state are dynamic.
The book I am reading does not mention this however, either due to an error, or a difference perhaps in versions of SignalR

Why try catch around highchart constructor does not catch error#12 but error#19?

I'm using highcharts 4.0.4 and trying to catch any error that occurs during rendering.
I was able to catch the error#19, but when error#12 occurs the control doesn't go to the catch block. Does anyone know what could be the reason ?
Function call for the error #12 is done without second function argument error(12);. The second function argument is responsible for stopping the code execution, so the code is not stopped.
Code from Highcharts 4.0.4:
/**
* Provide error messages for debugging, with links to online explanation
*/
error = function (code, stop) {
var msg = 'Highcharts error #' + code + ': www.highcharts.com/errors/' + code;
if (stop) {
throw msg;
}
// else ...
if (win.console) {
console.log(msg);
}
};
In Highcharts 5.0.0+ it is possible to override/extend/wrap the error function with you own code.

Getting the project base path in a yeoman generator

I have updated the yeoman generator dependency from 0.18.10 to 0.20.3.
I have updated the deprecated this.dest to this.destinationRoot()
I am now having issues with the generator when it comes to getting the base path of the project, so that I can copy files from one location to another.
I have created a function to put the paths together, this then passes to another function which excludes some files from being copied over.
Here is the function I getting the error with
// Copy Bower files to another directory
var copyBowerFiles = function (component, to, exclude) {
var base = this.destinationRoot(),
publicDir = base + '/' + this.publicDir,
publicAssetsDir = publicDir + '/assets',
bowerComponentsDir = publicAssetsDir + '/bower_components',
bower,
from;
to = (base + '/' + to || publicAssetsDir);
from = bowerComponentsDir + '/' + component;
//this.dest.copy(from, to);
this.bulkDirectory(from, copyDestPathPartial.call(this, to, exclude));
};
This is being called in the end function:
end: function () {
this.installDependencies({
callback: function () {
copyBowerFiles.call('jam', this.publicDir, excludeJamFiles);
}.bind(this)
});
}
I get the error message:
var base = this.destinationRoot(),
^
TypeError: undefined is not a function
I have also tried sourceRoot()
I would like to update my generator to work with the latest version of the generator. Any help getting this working would be great.
Also do you still have to pass this as the first parameter when calling a function?
EDIT:
Here is the copyDestPathPartial function
// Copy destination path partial
var copyDestPathPartial = function (to, exclude) {
exclude = exclude || [];
return function (abs, root, sub, file) {
if (!_.contains(exclude, file) && ! _.contains(exclude, sub)) {
this.copy(abs, to + '/' + (sub || '') + '/' + file);
}
}.bind(this.destinationRoot());
};
When I use this in the copyBowerFiles function I get another error message which says when I call this function:
throw new TypeError('Arguments to path.resolve must be strings');
Is the copyDestPathPartial function not outputting a string?
This is only a JavaScript error, this inside copyBowerFiles is not what you think it is.
With the code you wrote, this is equal to jam.
So here you'd want: copyBowerFiles.call(this, 'jam', this.publicDir, excludeJamFiles);. As the first argument to call is the this value. See documentation https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call
That being said, assigning random this value is very dirty and super hard to maintain. Why not making copyBowerFiles a prototype method?

Using forge.prefs always returns undefined

I'm trying to use forge.prefs to store variables but nothing seems to be saving.
I am using the following:
var all = forge.prefs.keys(function(keysArray){ return keysArray},
function(content){return content});
forge.logging.log(all);
But this always returns undefined
I am also having the same issue with setting, nothing seems to be working.
var set = forge.prefs.set(key,value,function(){},function(content){return content;});
forge.logging.log(set);
Again returns undefined and no error or anything.
Am I doing something wrong?
Using the docs found here
UPDATE
I won't to do something like the following:
var get = forge.prefs.get(key,
function(value){return value;},
function(error){forge.logging.log(error);
});
if(get){
// do something here
}else{
// do something here
}
Those methods are asynchronous which means that subsequent code might be executed before the callback success and error functions are returned. All subsequent code that relies on the outcome of this should run within the callback:
forge.prefs.keys(function(keysArray){ // success
forge.logging.log(keysArray);
// subsequent code relying on a positive outcome here ...
},
function(error){ // error
forge.logging.log('Something bad happened: ' + error);
});
forge.prefs.set(key, value, function(){ // success
forge.logging.log(key + ' was properly set);
// subsequent code relying on a positive outcome here ...
},
function(error){ // error
forge.logging.log('Something bad happened: ' + error);
});
UPDATE: use this to achieve the updated part of your question:
var get;
forge.prefs.get(key, function(value){ // success
get = value;
forge.logging.log('Found value: ' + get);
// subsequent code here ...
},
function(error){ // error
forge.logging.log('Something bad happened: ' + error);
});
It appears you're not returning anything in the forge.pref.set success function. Your return content; is in the error function so if it's not throwing an error you won't return anything.
Try this:
var set = forge.prefs.set(key,value,function(){ return value; },function(content){return content;});
forge.logging.log(set);

Resources