Frida Android: Hook StringBuilder and print data only from a specific class - security

I have hooked the StringBuilder class method toString by using this code
Java.perform(function() {
const StringBuilder = Java.use('java.lang.StringBuilder');
StringBuilder.toString.implementation = function() {
var res = this.toString();
var tmp = "";
if (res !== null) {
tmp = res.toString().replace("/n", "");
console.log(tmp);
}
return res;
};
});
This code is printing a ton of irrelevant data. I just want to print the data from a specific class/method. How it can be accomplished?
Thanks

I have not tested the code but the following should work:
Also hook the specific method that uses StringBuilder.toString() you are interested in and set a variable that enables your StringBuilder hooking code just while you are in that method:
var sbActivate = false;
Java.perform(function() {
const StringBuilder = Java.use('java.lang.StringBuilder');
StringBuilder.toString.implementation = function() {
var res = this.toString();
if (sbActivate) {
var tmp = "";
if (res !== null) {
tmp = res.toString().replace("/n", "");
console.log(tmp);
}
}
return res;
};
});
Java.perform(function() {
const someclass = Java.use('<the specific class you are interested in>');
someclass.someMethod.implementation = function() {
sbActivate = true;
var res = this.someMethod();
sbActivate = false;
return res;
};
});

Related

Struggling to use async await within for loops with nodejs

I am trying to use multiple functions within a for loop but, one is returning undefined (or not waiting?)
Code is as below:
var arrNew = [];
var id = [];
var get1 = [];
var get2 = [];
var get3 = [];
var res = [];
var get4 = [];
for (j = 0; j < arrNew.length; j++) {
id[j] = arrNew[j];
get1[j] = await get1Fun(context, id[j]);
if (get1[j] !== false) {
get2[j] = await get2Fun(context, get1[j]);
context.log(get2[j]);
if (get2[j].length) {
get3[j] = await get3Fun(context, get2[j]);
if (get3[j] !== false && get3[j].status == 200) {
res[j] = get3[j].result;
get4[j] = await get4Fun(context, id[j], res[j]);
context.log(get4[j])
}
}
}
}
async function get1Fun(context, id) {
const querySpec = {
query: `SELECT * FROM r where r.id = "${id}"`,
};
const { resources } = await client.database(databaseId).container(containerId).items.query(querySpec).fetchAll();
if (resources.length == 1) {
return resources[0];
} else if (!resources.length) {
return false;
}
}
function get2Fun(context, getInt) {
return new Promise((resolve, reject) => {
var msg = []
// do for loop stuff with getInt and push stuff into msg
context.log(msg)
resolve(msg);
});
}
The code works up until this point where get2Fun either returns undefined or if (get2[j].length) does not wait for await get2Fun.
Can someone clarify what is going wrong please?
I have tried with async function and without the promise.
The reason I have the arrays as below is because if I structured the function as var get1 = await get1Fun(context, id) then the for loop would stop after 1 or 2 items and not do every item in arrNew.
Thanks in advance.
EDIT:
Also tried the below but the for loop stops after 1 loop (presumably an issue with each loop redefining a variable?):
for (j = 0; j < arrNew.length; j++) {
var id = arrNew[j];
var get1 = await get1Fun(context, id);
if (get1 !== false) {
var get2 = await get2Fun(context, get1);
context.log(get2);
if (get2.length) {
var get3 = await get3Fun(context, get2);
if (get3 !== false && get3.status == 200) {
var res = get3.result;
var get4 = await get4Fun(context, id, res);
context.log(get4)
}
}
}
}
async function get1Fun(context, id) {
const querySpec = {
query: `SELECT * FROM r where r.id = "${id}"`,
};
const { resources } = await client.database(databaseId).container(containerId).items.query(querySpec).fetchAll();
if (resources.length == 1) {
return resources[0];
} else if (!resources.length) {
return false;
}
}
async function get2Fun(context, getInt) {
var msg = []
// do for loop stuff with getInt and push stuff into msg
context.log(msg)
return msg;
}

Why doesn't my async function return any result?

I wrote this small program to fetch data. This however is done async. Since I nonetheless need to use the function holeVertreter(kzl) as a function in another module, I'd like to get a return value which I can eventually pass on.
Excuse my spaghetti code (I usually prettify the code when I am done with my task ...).
Credentials are stored in a file and are therefore not found in this file.
I'd like to end up with "vertreter" as a return value.
Thank you in advance.
const node = require("deasync");
const DSB = require('dsbapi');
const tabletojson = require('tabletojson');
const https = require('https');
const cred = require("./vertrCred");
const dsb = new DSB(cred["dsb"]["user"], cred["dsb"]["passw"]); //Sanitized - no Credentials here
//Stackoverflow 2332811
String.prototype.capitalize = function(lower) {
return (lower ? this.toLowerCase() : this).replace(/(?:^|\s)\S/g, function(a) { return a.toUpperCase(); });
};
function holePlan(kuerzel) {
dsb.fetch()
.then(data => {
const timetables = DSB.findMethodInData('timetable', data);
const tiles = DSB.findMethodInData('tiles', data);
var tilesStr = JSON.stringify(tiles["data"][0]["url"]);
var url = JSON.parse(tilesStr);
https.get(url, (resp) => {
let data = '';
resp.on('data', (chunk) => {
data += chunk;
});
resp.on('end',() => {
var tableasjson = tabletojson.convert(data);
var erstetab = tableasjson[0];
var zweitetab = tableasjson[1];
var drittetab = tableasjson[2];
var viertetab = tableasjson[3];
var fuenftetab = tableasjson[4];
var sechstetab = tableasjson[5];
var siebtetab = tableasjson[6];
var achtetab = tableasjson[7];
if (typeof kuerzel === "undefined")
{
var regenechse = '(Aaa|Aaa[A-Za-z?]|[A-Za-z?]Aaa)';
}
else {
var name = kuerzel.capitalize(true);
var regenechse = '('+name+'|'+name+'[A-Za-z?]|[A-Za-z?]'+name+')';
}
const regex = new RegExp(regenechse,'g');
var sammel = Object.assign(drittetab,fuenftetab);
var z= 0;
var vertreter = {}
var y = JSON.parse(JSON.stringify(sammel));
for (i=0;i<y.length;i++) {
if (typeof y[i].Vertreter =='undefined') {
}
else {
if(y[i].Vertreter.match(regex))
{
z += 1;
vertreter[z] = y[i];
}
}
}
if (z == 0) {
// console.log("Es gibt nichts zu vertreten");
}
else {
//console.log("Es werden "+z+" Stunden vertreten");
return (vertreter);
} ;
});
})
})
.catch(e => {
// An error occurred :(
console.log(e);
});
}
//Stackoverflow
function warte(promise) {
var done = 0;
var result = null;
promise.then(
function (value) {
done = 1;
result = value;
return (value);
},
function (reason) {
done = 1;
throw reason;
}
);
while (!done)
node.runLoopOnce();
return (result);
}
function holeVertretung(kzl) {
var aufgabe = new Promise((resolve,reject) => {
setTimeout(resolve,1000,holePlan(kzl));
});
var ergebnis = warte(aufgabe);
if (typeof ergebnis === "undefined") {
console.log("Mist");
}
else {
console.log(ergebnis);
}
return ergebnis;
}
holeVertretung("Aaa");
That's not the right way to work with promises. If you do such infinite loop, it beats the whole purpose of using promises. Instead, return value from the promise, and use async-await like this:
function warte(promise) {
var done = 0;
var result = null;
return promise.then(
...
}
async function holeVertretung(kzl) {
var aufgabe = new Promise((resolve, reject) => {
setTimeout(resolve, 1000, holePlan(kzl));
});
var ergebnis = await warte(aufgabe);
...
If async-await does not work for some reason, use then clause:
warte(aufgabe).then(value => {
var ergebnis = value;
});

Deserialize strange querystring with Node.js

I have the following string and want to deserialize it to an object(s):
responseEnvelope.timestamp=2015-07-06T15%3A20%3A49.534-07%3A00
&responseEnvelope.ack=Failure&responseEnvelope.correlationId=a58a06c1000d8
&responseEnvelope.build=15743565&error(0).errorId=520003&error(0).domain=PLATFORM
&error(0).subdomain=Application&error(0).severity=Error&error(0).category=Application
(BTW - It is the response from PayPal Adaptive Payments using the Classic API)
https://developer.paypal.com/webapps/developer/docs/classic/api/adaptive-payments/Pay_API_Operation/
Using Node.js I can convert it into an array of items using
var qs = require('querystring');
var response = the-response-from-paypal;
var paypalResponse = qs.parse(response.toString());
console.log(paypalResponse["responseEnvelope.ack"])
//Renders: Failure
but I want to convert it into an object, that can be accessed like:
var ack = deserializedResponse.responseEnvelope.ack;
//etc
Or as JSON:
{
responseEnvelope: {
ack: "Failure",
timestamp: blah,
correlationId: "a58a06c1000d8",
...
},
error: [
{
errorId: 520003,
domain: "Platform",
...
}
]
}
Is there some handy tool to do this?
Basing this off of my answer for your other SO question. You would just need to wrap the recursion function in a preprocess that would build the entire object for you.
var newObj = input.split('&').reduce(function (o, str) {
var pair = str.split('=');
return setObjVal(o, pair[0].split('.'), pair[1]);
}, {});
function setObjVal(obj, paths, val) {
var path;
var arrayInfo;
if (paths.length === 0) {
return val;
}
obj = obj || {};
path = paths.shift();
arrayInfo = path.match(arrayRegExp);
if (arrayInfo) {
path = arrayInfo[1];
if (!Array.isArray(obj[path])) {
obj[path] = [];
}
obj[path][arrayInfo[2]] = setObjVal(obj[path][arrayInfo[2]], paths, val);
}
else {
obj[path] = setObjVal(obj[path], paths, val);
}
return obj;
}
var arrayRegExp = /^(\w+)\((\d+)\)$/;
var input = 'responseEnvelope.timestamp=2015-07-06T15%3A20%3A49.534-07%3A00&responseEnvelope.ack=Failure&responseEnvelope.correlationId=a58a06c1000d8&responseEnvelope.build=15743565&error(0).errorId=520003&error(0).domain=PLATFORM&error(0).subdomain=Application&error(0).severity=Error&error(0).category=Application';
var newObj = input.split('&').reduce(function (o, str) {
var pair = str.split('=');
return setObjVal(o, pair[0].split('.'), pair[1]);
}, {});
function setObjVal(obj, paths, val) {
var path;
var arrayInfo;
if (paths.length === 0) {
return val;
}
obj = obj || {};
path = paths.shift();
arrayInfo = path.match(arrayRegExp);
if (arrayInfo) {
path = arrayInfo[1];
if (!Array.isArray(obj[path])) {
obj[path] = [];
}
obj[path][arrayInfo[2]] = setObjVal(obj[path][arrayInfo[2]], paths, val);
}
else {
obj[path] = setObjVal(obj[path], paths, val);
}
return obj;
}
document.write('<pre>' + JSON.stringify(newObj, null, 4) + '</pre>');
Alternatively if you want to use lodash as in the other answer you could use _.set():
var newObj = input.split('&').reduce(function (o, str) {
var pair = str.split('=');
return _.set(o, pair[0].replace(/\(/g, '[').replace(/\)/g, ']'), pair[1]);
}, {});
var input = 'responseEnvelope.timestamp=2015-07-06T15%3A20%3A49.534-07%3A00&responseEnvelope.ack=Failure&responseEnvelope.correlationId=a58a06c1000d8&responseEnvelope.build=15743565&error(0).errorId=520003&error(0).domain=PLATFORM&error(0).subdomain=Application&error(0).severity=Error&error(0).category=Application';
var newObj = input.split('&').reduce(function (o, str) {
var pair = str.split('=');
return _.set(o, pair[0].replace(/\(/g, '[').replace(/\)/g, ']'), pair[1]);
}, {});
document.write('<pre>' + JSON.stringify(newObj, null, 4) + '</pre>');
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.0/lodash.min.js"></script>

Nodejs streams writablestream drain event not firing

I am trying to read in a large file, do some computation and then write to a much bigger file. To prevent excessive memory consumption, I am using streams. The problem that I am facing is that the writestream is not firing the "drain" event, which signals that the writes have been flushed to disk. In order to prevent "back-pressure", I am waiting for the drain event to be fired before I start writing to the buffer again. While debugging I found that after a .write() call returns false and the line fvfileStream.once('drain', test) is executed, the program just stops and does not do anything.
Here is the code:
var fs = require('fs');
//a test function I created to see if the callback is called after drain.
var test = function(){
console.log("Done Draining");
}
fs.readFile('/another/file/to/be/read', {
encoding: "utf8"
}, function(err, data) {
if (err) throw err;
//Make an array containing tags.
var tags = data.split('\n');
//create a write stream.
var fvfileStream = fs.createWriteStream('/path/TagFeatureVectors.csv');
//read in the question posts
var qfileStream = fs.createReadStream('/Big/file/QuestionsWithTags.csv', {
encoding: "utf8"
});
var partialRow = null;
var writable = true;
var count = 0;
var doRead = function() {
var qData = qfileStream.read();
var questions = qData.split('\n');
if (partialRow != null) {
questions[0] = partialRow + questions[0];
partialRow = null;
}
var lastRow = questions[questions.length - 1];
if (lastRow.charAt(lastRow.length - 1) != '\n') {
partialRow = lastRow;
}
questions.forEach(function(row, index, array) {
count++;
var fields = row.split(',');
console.log("Processing question number: " + count + " id: " + fields[0]);
var tagString = fields[1];
var regex = new RegExp(/<([^>]+)>/g);
tags.forEach(function(tag, index, array) {
var found = false;
var questionTags;
while ((questionTags = regex.exec(tagString)) != null) {
var currentTag = questionTags[1]
if (currentTag === tag) {
found = true;
break;
}
};
//This is where the writestream is written to
if (found) {
writable = fvfileStream.write("1,", "utf8");
}else {
writable = fvfileStream.write("0,","utf8");
}
});
});
fvfileStream.write("\n");
}
qfileStream.on('readable', function() {
if (writable) {
doRead();
} else {
//Waiting for drain event.
fvfileStream.once('drain', test);
}
});
qfileStream.on('end', function() {
fvfileStream.end();
});
});
Updated
Based on advise provided by #loganfsmyth, I implemented transform streams, but still ran into the same issue. Here is my updated code:
var fs = require('fs');
var stream = require('stream');
var util = require('util');
var Transform = stream.Transform;
function FVCreator(options) {
// allow use without new
if (!(this instanceof FVCreator)) {
return new FVCreator(options);
}
// init Transform
Transform.call(this, options);
}
util.inherits(FVCreator, Transform);
var partialRow = null;
var count = 0;
var tags;
FVCreator.prototype._transform = function(chunk, enc, cb) {
var that = this;
var questions = chunk.toString().split('\n');
if (partialRow != null) {
questions[0] = partialRow + questions[0];
partialRow = null;
}
var lastRow = questions[questions.length - 1];
if (lastRow.charAt(lastRow.length - 1) != '\n') {
partialRow = lastRow;
questions.splice(questions.length - 1, 1);
}
questions.forEach(function(row, index, array) {
count++;
var fields = row.split(',');
console.log("Processing question number: " + count + " id: " + fields[0]);
var tagString = fields[1];
var regex = new RegExp(/<([^>]+)>/g);
tags.forEach(function(tag, index, array) {
var found = false;
var questionTags;
while ((questionTags = regex.exec(tagString)) != null) {
var currentTag = questionTags[1]
if (currentTag === tag) {
found = true;
break;
}
};
if (found) {
that.push("1,", "utf8");
} else {
that.push("0,", "utf8");
}
});
});
this.push("\n", "utf8");
cb();
};
fs.readFile('/another/file/to/be/read', {
encoding: "utf8"
}, function(err, data) {
if (err) throw err;
//Make an array containing tags.
tags = data.split('\n');
//write to a file.
var fvfileStream = fs.createWriteStream('/path/TagFeatureVectors.csv');
//read in the question posts
var qfileStream = fs.createReadStream('/large/file/to/be/read', {
encoding: "utf8"
});
var fvc = new FVCreator();
qfileStream.pipe(fvc).pipe(fvfileStream);
});
I am running this on OSX Yosemite.

Node.js - TypeError: Object #<Object> has no method

I am trying to include a module i found that will help manage users:
http://www.codeproject.com/Articles/382561/Session-Management-in-Nodejs
Ive copied the code and put it in the same directory as my server.js
I require it by doing:
var express = require('express');
var http = require('http'),
mysql = require("mysql");
var server = http.createServer(app);
var io = require('socket.io').listen(server);
var sessionMgm = require("./sessionManagement");
Now in my socket i do this:
io.sockets.on('connection', function (socket) {
socket.on('setUserInfo', function (data) {
var sess = new Object();
sess.sessionId = socket.id;
sess.userId = data.userId;
sess.username = data.username;
sess.role = data.role;
sessionMgm.add(sess);
});
socket.on("private", function(data) {
if(data.agentName.length <= 0) {
data.agentName = 'Besökare';
}
io.sockets.in('Room_' + data.user_id).emit('updatechat', data.agentName, data.msg);
var user = sessionMgm.getSessionByUserId(data.id);
console.log('::: A socket with ID ' + user + ' connected! ::: ');
});
});
However i keep getting this error:
TypeError: Object # has no method 'getSessionByUserId'
Cant seem to figure out whats wrong, any ideas?
sessionManagement.js:
module.exports = sessionManagement;
var sessions = [];
//User roles list
var userRoles = {
Admin: "administrator",
User: "user",
Supervisor: "supervisor"
};
var sessionManagement = {
indexOf: function(sessionId) {
for(var i in sessions) {
if(sessions[i].sessionId == sessionId)
return i;
}
return null;
},
indexOfUser: function(userId) {
for(var i in sessions) {
if(sessions[i].userId == userId)
return i;
}
return null;
},
add: function(sessionData) {
sessions.push(sessionData);
},
remove: function(sessionId) {
var index = this.indexOf(sessionId);
if(index != null) {
sessions.splice(index, 1);
} else {
return null;
}
},
removeByUserId: function(userId) {
var index = this.indexOf(userId);
if(index != null) {
sessions.splice(index, 1);
} else {
return null;
}
},
getSessionById: function(userId) {
var index = this.indexOfUser(userId);
if(index != null) {
return sessions[index];
} else {
return null;
}
},
getSessionByUserId: function(sessionId) {
var index = this.indexOfUser(userId);
if(index != null) {
return sessions[index];
} else {
return null;
}
},
isAdmin: function(userId) {
var index = this.indexOfUser(userId);
if(index != null) {
if(users[index].role == userRoles.Admin) {
return true;
} else {
return false;
}
} else {
return null;
}
},
getUsersByRole: function(role) {
var usersByRole = [];
for(var i in users) {
if(users[i].role == role)
usersByRole.push(users[i]);
}
return usersByRole;
}
};
As madflow mentioned, you were missing module.exports = sessionManagement in sessionManagement.js
Then you got the error, because you were exporting sessionManagement, before initializing it. Moving the export line to the end of sessionManagement.js should fix that.
module.exports = sessionManagement; // <- you export here
...
...
...
var sessionManagement = { // and initialize here
Although sessionManagement declaration gets hoisted to the top of the module (and that's why you don't get Unexpected identifier or ReferenceError when assigning it to module.exports), it's initialization does not, so what really happens behind the scenes is something like that:
var sessionManagement; // undefined at this point
module.exports = sessionManagement; // <- you export here,
// but sessionManagement is undefined at this point
// and so will be module.exports after this line
...
...
...
sessionManagement = { // and initialize here

Resources