I tried to implement node-global-key-listener package for my project and was successful in Windows build as well as in Mac.When I tried it in Ubuntu, for some reason the listener is not listening. I am currently in v20.04.
Upon tracing the code, this listener on the x11ServerKey does not seem to get called.
this.proc.stdout.on("data", data => {
const events = this._getEventData(data);
for (let { event, eventId } of events) {
const stopPropagation = !!this.listener(event);
this.proc.stdin.write(`${stopPropagation ? "1" : "0"},${eventId}\n`);
}
});
The process child does get initialized. Just listener not listening. The cpp part is a little outside of my expertise.
Any idea how to go about this? Let me know if you need more info.
Thank you so much.
I have traced the code up to the part where x11 server key is getting executed as a node child process. I think it is getting initialized but it is not emitting the on 'data' that handles the event.
Related
I have a non-common use case I'd like to implement. I found an open source project that uses puppeteer to automate action within whatsapp web. It provides a client object with an API to listen to events or do some actions such as
client.on('message_create', (msg) => {
client.sendMessage(number, text);
});
I'm not so proficient with JS, but what I understand is that it launches a real instance of whatsapp web and then interacts with it.
What I want to do is - once whatsapp web is loaded, add a div with buttons that would interact with my wrapper app functions and do automated stuff.
I did manage to add external button to the UI and set it's onClick, I done it via the the page.evaluate function, something like that:
await client.puppeteerPage.evaluate(async () => {
let btn = document.querySelector('#updateIcButton');
btn.addEventListener("click", async ()=>{
// Do some action with the client, however - client is undefined here
});
});
So far so good, but now comes the problem - what I want to do is to interact with the client functions inside the click listener, which I currently found impossible to do since inside the 'evaluate' function which is the only way I found to inject buttons, the client from the upper scope is undefined... I couldn't find a way to pass the client object as it creates a cyclic dependency or something if I pass as parameter.. Also tried other stuff such as calling exposeFunction or addScriptTag but nothing seem to be working.
I'm not sure it's possible anyhow, as although I'm not so proficients with JS and web dev, I understand that the web page doesn't "know" or can't interact with the puppeteer application wrapping it.
I'd appreciate if someone can please suggest a way to solve or another possible way to add UI that can interact with my puppeteer application and do automated stuff within the page instance.
Appreciate your help!
More of my source code:
client.on('ready', async () => {
await client.pupPage.exposeFunction("sendMessage", client.sendMessage);
client.pupPage.evaluate((divHtml) => {
//here I have logic to load a div container with a single button
//Once the div is added, I'm querying the button ID and trying to set it's onClick to interact with the client from above
let btn = document.querySelector('#updateIcButton');
btn.addEventListener("click", async ()=>{
// Do some action with the client
sendMessage("phonenumber","sometext"); // trying to call the func I exposed
});
}, divHtml);
});
I am using node.js 14 and currently have a loop that is made by a recursive function and a setTimeout, something like this:
this.timer = null;
async recursiveLoop() {
//Do Stuff
this.timer = setTimeout(this.recursiveLoop.bind(this), rerun_time);
}
But sometimes this loop gets stuck and I want it to automatically notice it, clean up and restart. So I tried doing something like this:
this.timer = null;
async recursiveLoop() {
this.long_timer = setTimeout(() => throw new Error('Taking too long!'), tooLong);
//Do Stuff
this.timer = setTimeout(this.recursiveLoop.bind(this), rerun_time);
}
main() {
//Do other asynchronous stuff
recursiveLoop()
.then()
.catch((e) => {
console.log(e.message);
cleanUp();
recursiveLoop();
}
}
I can't quite debug where it gets stuck, because it seems quite random and the program runs on a virtual machine. I still couldn't reproduce it locally.
This makeshift solution, instead of working, keeps crashing the whole node.js aplication, and now I am the one stuck. I have the constraint of working with node.js 14, without using microservices, and I never used child process before. I am a complete beginner. Please help me!
If you have a black box of code (which is all you've given us) with no way to detect errors on it and you just want to know when it is no longer generating results, you can put it in a child_process and ask the code in the child process to send you a message every time it runs an iteration. Then, in your main process, you can set a timer that resets itself every time it gets one of these "health" messages from the child. If the timer fires without getting a health message, then the child must be "stuck" because you haven't heard from it within your timeout time. You can then kill the child process at that point and restart it.
But, that is a giant hack. You should FIX the code that gets stuck or at least understand what's going on. Probably you're either leaking memory, file handles, database handles, running code that uses locks and messes up or there are unhandled errors happening. All are indications of code that should be fixed.
I'm trying to bypass a root detection mechanism on an android app using Frida, I've tried so many different scripts (frida code share) and different approaches (like hiding root) with no luck!
So I tried to locate the class and method responsible for checking if the device is rooted or not and changing it's return value.
This is my script :
setTimeout(function() { // avoid java.lang.ClassNotFoundException
Java.perform(function() {
var hook = Java.use("app.name.RootUtils");
console.log("info: hooking target class");
hook.isRooted.overload().implementation = function() {
console.log("info: entered target method");
return Java.use("java.lang.Boolean").$new(false);
}
});
},0);
If I inject this code normally it won't work because it looks like the isRooted method will get called before it
If I use spawn to run the app and change this method return value it fails with error :
frida.core.RPCException: Error: java.lang.ClassNotFoundException: Didn't find class ...
I've also tried spawning the app and then using objection to run "android root disable" but it will return this error :
frida.core.RPCException: TypeError: cannot read property 'getApplicationContext' of null
at getApplicationContext (src/android/lib/libjava.ts:21)
I'm not sure if this is a problem with Frida or my system or ...
I think if I was able to make my main code runs at exactly after the class gets loaded (like using a loop to check or using a hook) the problem would be fixed but I don't know how to write that kind of code in js for frida.
I'm on macOS 11.5.1 using python 3.9 and installed latest version of frida and objection
I've tested on one rooted phone with android 10 and an emulator with android 6
I was able to solve this issue with a simple yet not very technical solution.
I used a setInteval to run my hooking over and over until it gets to work, (as #Robert mentioned, I also needed to wrap hooking inside a try catch to prevent the code from stoping after first try)
This may not work for everyone but since it worked for me I will post the final code, may it helps someone else in the future :)
Java.perform(function() {
var it = setInterval(function(){
try{
var hook = Java.use("app.name.RootUtils");
console.log("info: hooking target class");
hook.isRooted.overload().implementation = function() {
console.log("info: entered target method");
clearInterval(it);
return Java.use("java.lang.Boolean").$new(false);
}
} catch(e) {
console.log("failed!");
}
},200); // runs every 200milisecods
});
PS : you may need to change interval time to match your app needs, it worked for me with 200 miliseconds.
Sometimes app would do encryptions in its class loader, you may need to replace Java.classFactory.loader with the app's customized class loader in order to make Java.use function properly.
Here's how it's done:
Java.perform(function() {
//get real classloader
//from http://www.lixiaopeng.top/article/63.html
var application = Java.use("android.app.Application");
var classloader;
application.attach.overload('android.content.Context')
.implementation = function(context) {
var result = this.attach(context); // run attach as it is
classloader = context.getClassLoader(); // get real classloader
Java.classFactory.loader = classloader;
return result;
}
//interesting classes
const interestingClassPath = "com.myApp.SometingInteresting";
interestingClass = Java.use(interestingClassPath);
//do whatever you like here
})
Class not found
How do you know the class is app.name.RootUtils have you decompiled to app using Jadx or apktool? How about the method where RootUtils.isRooted() is called? Is there any special code that loads the RootUtils class e.g. from a non-standard dex file included in the app? If the class is loaded from a special dex file you could hook this dex loading mechanism and first execute it and then install your hook for RootUtils.isRooted().
Alternatively assuming RootUtils.isRooted() is called only from one other method and does not use special code for loading the RootUtils class you could hook that method and use the this hook to install install your RootUtils.isRooted() hook.
Error handling
The correct way to handle errors in JavaScript is using try catch block, not the setTimeout function:
Java.perform(() => {
try {
var hook = Java.use("app.name.RootUtils");
...
} catch (e) {
console.log("Failed to hook root detection" + e);
}
}
Regarding your problems hooking the class
For background purposes I made a deep search in ionic documentation (native and no native), and in other pages, and found that may be there is a posibility to achieve this (keep running a subscription even the app was closed), but I can't understand at all where I should put one thing or other thing to make BakckgroundMode plugin working... (I think this plugin is not working in my device), but it's hard to inspect that thing because you can't inspect your device if it's in background mode with chrome://inspect...
This is the BackgroundMode plugin:
https://github.com/katzer/cordova-plugin-background-mode
I have installed backgroundMode 0.7.2 which isn't the most actualized plugin, but trying to install the latest gives me errors on build, so i tried this version and works.
In the docs, I see the following:
The plugin creates the object cordova.plugins.backgroundMode and is
accessible after the deviceready event has been fired.
So in order to run background mode, in my page.ts inside constructor (later I will talk about why in the constructor), I put:
document.addEventListener('deviceready', ()=> {
this.backgroundMode.enable();
this.backgroundMode.setDefaults(
{
title: 'executing in bg mode...',
text: 'background mode was activated successfully!',
color: '#fff',
resume: true,
silent: false
}
);
this.backgroundMode.disableWebViewOptimizations();
this.backgroundMode.on('activate').subscribe(()=>{
this.isAcceptedObservable = this.localNotifications.on('yes').subscribe(res =>{
console.log('confirmed!');
this.backgroundMode.unlock();
});
//And more observables...
});
});
the subscriptions inside backgroundMode.on('activate') subscription are the things that I need to keep running even if app is closed.
the reason of why I was put that code in constructor is because I'm using also ngx-socket-io to listen to emit and broadcast functions of a socket server in node that i created, so one of the subscriptions that is linked to socket events is:
this.getInvitationSubscriber = this.getInvitation().subscribe(data =>{
this.invitations.push(data);
this.showNotification({
title: 'Invitation received!',
text: 'Someone invited you!',
icon: data['from']['avatar_src'],
attachments: [data['from']['invitation_src']]
});
console.log(this.invitations);
});
in ionViewWillEnter i call:
ionViewWillEnter{
this.socket.connect();
}
and this function is outside the constructor:
getInvitation(){
let observable = new Observable(observer =>{
this.socket.on('subject', data =>{
observer.next(data);
});
});
return observable;
}
I'm expecting to keep running the 'notifications listener' that I have in constructor inside the backgroundMode.on('activate') function to receive notifications even app is closed, but I dont know if it's possible with ngx-socket-io and the structure that i have.
also I have injected background mode in app.module providers and in otherpage.module.ts provider and imported correctly so that's not the error, but I'm not getting notifications...
I know that notifications scheduling are correct because if i simple try not to use backgroundMode and putting that subscriptions outside backgroundMode.on('activate') subscription, i'm getting again notifications, but only works if app is in foreground or in suspended...
I'm just now getting into node.js and reading input from the command line.
I'm a bit confused on the following code example.
process.stdin.setEncoding('utf8');
process.stdin.on('readable', () => {
var chunk = process.stdin.read();
if (chunk !== null) {
process.stdout.write(`data: ${chunk}`);
}
});
process.stdin.on('end', () => {
process.stdout.write('end');
});
First, in old mode, process.stdin.resume() was needed to make it begin to listen. Doesn't using resume() make more sense for performance? Doesn't this continually listen, using up processing power that it doesn't need to use up?
Also, I read the docs but I'm not understanding what 'end' does here.
The docs say:
This event fires when there will be no more data to read.
But 'readable' is always listening so we never get to the 'end'?
Continually listening for input doesn't necessarily use more resources than resuming the stream manually. It's just a different way of handling the pipes.
The "readable" part stops listening when the "end" event is triggered, as end will close the stream and therefore there won't be anything readable anymore.
The end event is a translation of the end signal fired to the standard input (for instance a CTRL/D on a unix system.