[Q] problem with class static value - Xposed General

have some problems with static values used as flags.
for example I need to hook 2 methods in different FRAMEWORK classes during initZygote. (no problem with system apps during handleLoadPackage)
I hook method in first class, set static value and waiting when another method of another class will be triggered.
once another method is invoked, flag always has it's initial state.
it looks like each hook method processed in different class instances.
i tried volatile type, tried to synchronize - nothing help.
unreliable remedy:
1. register broadcast receiver inside hook method.
2. send action to own service
3. send broadcast from own service.
4. catch broadcast with receiver.
BUT it is not battery cost efficient solution in my case. And mostly I receive broadcast message when hooking method already processed and returned value. Otherwise I need to wait when service will process request and send broadcast. But it is not usable.
is there any solution?
Code:
public class XMain implements IXposedHookInitPackageResources, IXposedHookZygoteInit, IXposedHookLoadPackage
{
private static boolean isNeedToRun = false;
public void initZygote(StartupParam startupParam) throws Throwable
{
findAndHookMethod("com.class1", null, "method1", int.class, new XC_MethodHook()
{
@Override
protected void beforeHookedMethod(final MethodHookParam param) throws Throwable
{
isNeedToRun = true;
}
});
findAndHookMethod("com.class2", null, "method2", int.class, new XC_MethodHook()
{
@Override
protected void beforeHookedMethod(final MethodHookParam param) throws Throwable
{
if (isNeedToRun) param.setResult(null); // always FALSE even if previous hook set as TRUE
}
});
}
}

Why do you think that using a broadcast receiver is not battery efficient?

GermainZ said:
Why do you think that using a broadcast receiver is not battery efficient?
Click to expand...
Click to collapse
I do not want to invoke service and send broadcast very often (several thousands times during normal battery one cycle charge)
I just want use easiest way by storing flag inside class and worried that users will find the module in the list of gluttonous applications.

Falseclock said:
Code:
if (isNeedToRun) param.setResult(null); // always FALSE even if previous hook set as TRUE
Click to expand...
Click to collapse
You're probably not considering the fact that different processes will each have its own "isNeededToRun" variable.
Whenever new processes (system_process, apps, etc.) are forked from zygote, each of them will have its own independent state which includes this static variable. From then on they will be completely separate things even if it's a variable with the same name, don't get confused by that.
Try adding a Log.i(...) call to write something in both methods, and then check the logcat for the pid in which the messages are logged. I bet you'll see that different pids are writing and reading, and you can't expect them to be doing it in the same global variable.

Tungstwenty said:
You're probably not considering the fact that different processes will each have its own "isNeededToRun" variable.
Whenever new processes (system_process, apps, etc.) are forked from zygote, each of them will have its own independent state which includes this static variable. From then on they will be completely separate things even if it's a variable with the same name, don't get confused by that.
Try adding a Log.i(...) call to write something in both methods, and then check the logcat for the pid in which the messages are logged. I bet you'll see that different pids are writing and reading, and you can't expect them to be doing it in the same global variable.
Click to expand...
Click to collapse
Yes, I realized this. But under handleLoadPackage everything work perfect.
Any suggestion to solve situation?

Falseclock said:
Yes, I realized this. But under handleLoadPackage everything work perfect.
Any suggestion to solve situation?
Click to expand...
Click to collapse
handleLoadPackage is executed after the fork, in the new process. Not sure what exactly you hooked when you tried that way, but probably both callbacks were executed in the same app/process.
You have the typical problem that requires some kind of inter-process communication (IPC). Most common examples for IPC in Android are broadcasts and services. Files might also be an option (especially with observers), but probably not when you need to change the value very frequently.

Related

[Q] Modifying notification

Hi folks,
even though there are many nice 3rd party twitter clients available they are all missing an important feature: push notifications using GCM. The original Twitter app offers GCM based notifications but the app itself is more or less crap.
Therefore I thought about utilizing the original Twitter app for receiving GCM messages which create the Android notifications and then modify these notifications so that another (3rd party) app is started when clicking on them. I already managed to hook into the NotificationManager:
Code:
XposedHelpers.findAndHookMethod(android.app.NotificationManager.class, "notify", String.class, int.class, Notification.class, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
XposedBridge.log("NotificationManager.beforeHookedMethod(): param=" + param);
for (Object o : param.args) {
if (o instanceof Notification) {
Notification n = (Notification) o;
XposedBridge.log("NotificationManager.beforeHookedMethod(): notification=" + n);
}
}
}
}
);
At this stage, where simple things as changing Notification.tickeText work, I tried the following:
1) Creating a new PendingIntent and assigning it to Notification.contentIntent:
Code:
Intent LaunchIntent = context.getPackageManager().getLaunchIntentForPackage("it.mvilla.android.fenix");
PendingIntent contentIntent = PendingIntent.getActivity(context, 0, LaunchIntent, 0);
n.contentIntent = contentIntent;
This fails due to the fact that I did not succeed in getting my hand on a Context instance. Does anyone have got an idea on how to get a Context instance or can provide another possibility for creating the PendingIntend without a Context?
2) As the previous did not work due to a missing Context I tried to change the LauchIntent of the existing Notification. But I was not able to find the correct place - I did not even find the original LaunchIntent when studying the sources or even by dumping the notification by reflection.
I also started investigating on how to hook into the Twitter app itself. But as the source code is (of course) not public and additionally is obfuscated this seems to be even more complicated. In addition hooking into the NotificationManager is more generic and would allow - when adding configuration - the redirection also for other sources and targets.
As you see, I am somehow stucked. But I'm not hopeless respectively cannot imaging that it should not be possible. So now it's up to you to feed me with the correct ideas
So far and thanks in advance,
yaan04
yaan04 said:
1) Creating a new PendingIntent and assigning it to Notification.contentIntent:
This fails due to the fact that I did not succeed in getting my hand on a Context instance. Does anyone have got an idea on how to get a Context instance or can provide another possibility for creating the PendingIntend without a Context?
Click to expand...
Click to collapse
AndroidAppHelper.currentApplication() should do the trick. Otherwise see this, though if AndroidAppHelper fails most of these probably will, too.
yaan04 said:
2) As the previous did not work due to a missing Context I tried to change the LauchIntent of the existing Notification. But I was not able to find the correct place - I did not even find the original LaunchIntent when studying the sources or even by dumping the notification by reflection.
Click to expand...
Click to collapse
LaunchIntent?
yaan04 said:
I also started investigating on how to hook into the Twitter app itself. But as the source code is (of course) not public and additionally is obfuscated this seems to be even more complicated. In addition hooking into the NotificationManager is more generic and would allow - when adding configuration - the redirection also for other sources and targets.
Click to expand...
Click to collapse
Android API calls won't be obfuscated. Try searching for "NotificationManager" for example and see where it's used.
Yeah, AndroidAppHelper.currentApplication() provides a usable Context instance \o/
Thanks, GermainZ. Now I can go on...

[Q] Xposed - How to get the package name of a process

Hello,
I'm building an xposed module and i want to hook a method only if certain process (app) called this method. I can get the process pid and uid using Binder, but I can't find a way to get the package name.
How can I get it?
Thanks, Gidi
You can get it the usual way if you have a context. It might be a better idea to do something like this, depending on what you're trying to do:
Java:
public class XposedMod implements IXposedHookLoadPackage {
private int mHookedAppUid; // You can use this field to directly compare the UID.
[user=439709]@override[/user]
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
if (!lpparam.packageName.equals("package"))
return;
mHookedAppUid = lpparam.appInfo.uid;
}
}
GermainZ said:
You can get it the usual way if you have a context. It might be a better idea to do something like this, depending on what you're trying to do:
Java:
public class XposedMod implements IXposedHookLoadPackage {
private int mHookedAppUid; // You can use this field to directly compare the UID.
[user=439709]@override[/user]
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
if (!lpparam.packageName.equals("package"))
return;
mHookedAppUid = lpparam.appInfo.uid;
}
}
Click to expand...
Click to collapse
Thanks, but i still can't find a good way to get it.
for my example, i'm trying to hook the method sendTextMessage from android.telephony.SmsManager
if i do it using handleLoadPackage, it doesn't seems to work, but if i do it using initZygote it does work (i'm able to hook the method)
and since i don't have a Context, i can't do it in the usual way, and it seems i'm doing something wrong, since i can't use the other way too...
any idea?
You should use handleLoadPackage for the app you want (e.g. AOSP SMS app), it's independent from the initZygote hook and only there to store the UID.
Otherwise, you can try AndroidAppHelper.currentApplication() to get a context. This may not always return a context, though.

[Q] Inject Meta-Data from Manifest possible?

I'm trying to use Google Play Services APIs in a hooked method, but Google Play Services complains that I'm missing its version specification in the applications manifest, which makes sense since the application of which I hook the method doesn't integrate Google Play Services so its missing the meta-data tag from the manifest. Is there a way to inject the following meta-data into the hooked method's application process?
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
Or any alternative approach? Sorry if this has come up before, I'm a noob and I tried searching but didnt come up with anything.
As far as I know thats not possible.
You can try to hook the PackageManager and change the returned data to fool the check which is made. Not sure about other side effects, though.
theknut said:
You can try to hook the PackageManager and change the returned data to fool the check which is made. Not sure about other side effects, though.
Click to expand...
Click to collapse
Thanks for the suggestion! I tried hooking the method from PackageManager, but I must be missing something as I cant hook it and there is no error in the xposed log.
I wrote a quick test app com.example.overridetest which uses this code to get some meta-data from the manifest, which works fine:
Code:
localApplicationInfo = getPackageManager().getApplicationInfo("com.example.overridetest", 128);
Bundle localBundle = localApplicationInfo.metaData;
localBundle.getInt("com.google.android.gms.version");
Log.w("myApp", "metadata is "+i);
now im trying to hook getApplicationInfo in order to overwrite what it returns, however Im not able to hook it and theres no error in the xposed log either:
Code:
public void handleLoadPackage(final LoadPackageParam lpparam) throws Throwable {
if (!lpparam.packageName.equals("com.example.overridetest"))
return;
XposedHelpers.findAndHookMethod("android.content.pm.PackageManager", lpparam.classLoader, "getApplicationInfo", String.class, int.class, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(XC_MethodHook.MethodHookParam param) throws Throwable {
XposedBridge.log("getApplicationInfo Hooked");
}
});
Subbed!
This sounds interesting

[Q] call startService from hook method

Hello,
I've succeeded to hook method that gives me the accelerometer events.
so now all the application which use the accelerometer are generating events.
I wanted to send all those events from the hooking method to a service using intents that will aggregate them
and write them into a sqlite db (the db is not relevant for now, only the service).
The problem is that i can't start the intentService from the hook method.
Things that i tried already:
-- getting the Context from the activity on load by hooking the onStart in the Activity.class (succeeded getting the context but not starting the Service with an intent)
-- using the same context as above but start a broadcast receiver with implicit intent (define intent-filter in the manifest), and from the
broadcast to start the service (not worked either, the broadcast never got the sent message)
is there some guide or tutorial that can show me how to start a service or broadcast receiver from the hook method?
thanks ahead...
- make sure your service is defined in the manifest
- instead of IntentService, consider using standard service to which you can bind using context.bindService together with ServiceConnection object (see developer.android.com). You can use messenger approach for data exchange. This would be more efficient in your case.
As an example, I am using that approach in the following scenario:
I need to process screenshot taken during screen off in DisplayPowerController using my application context as I need to write image file within my module's filesDir
- I have a service within my module that receives image data and writes them to a file.
- I am binding to this service using bindService from within DisplayPowerController. It sends image data in chunks.
See this commit for more info:
https://github.com/GravityBox/GravityBox/commit/ad09553eaf0c669c4dcb8233a6b9706d1d939761
Call from other app context
First thanks for your answer,
Just to make it clear lets say i don't have any application,
i want to make some monitoring module on my phone which record all the Accelerometer events
request by different apps installed on my phone.
So there is general hook that tracking all the Accelerometer events, but when from those apps
or hook (the apps not mine but some apps i downloaded from the google play store), i want to
start a service or broadcast using their app context (taken from the activity or something).
The broadcast or service will not start (i think something with sandbox or that the apps and the service are not under the same context)
**that what i understood, maybe it's just some mistake in my code**
For example that some test i made:
Main Hook class:
public class TestHook implements IXposedHookLoadPackage{
@override
public void handleLoadPackage(LoadPackageParam lpparam) throws Throwable {
XposedBridge.hookAllMethods(Activity.class,"onStart", new XC_MethodHook()
{
@override
protected void beforeHookedMethod(MethodHookParam param)
throws Throwable {
Context context = (Context)param.thisObject;
if(context != null){
XposedBridge.log("sending brod...");
context.sendBroadcast(new Intent("com.example.logging"));
} else {
XposedBridge.log("not sending");
}
}
});
}
}
The receiver:
public class BrodTest extends BroadcastReceiver{
@override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Toast.makeText(context, "Got BroadCast", Toast.LENGTH_LONG).show();
}
}
and the manifest:
<manifest xmlns:android=
package="com.example.testproject"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="19" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<receiver android:name=".BrodTest">
<intent-filter>
<action android:name="com.example.logging"/>
</intent-filter>
</receiver>
<!--Declaration of the Xposed framework -->
<meta-data
android:name="xposedmodule"
android:value="true" />
<meta-data
android:name="xposedminversion"
android:value="30+" />
<meta-data android:name="xposeddescription"
android:value="Recording Sensors and Transmission events"/>
</application>
</manifest>
just tried to make some hook that will send to broadcast and show Toast message...
Thanks again...
I don't see anything wrong with the code. It should work.
Do you get a log message that the broadcast was sent?
Exported receiver?
Receiver log
The log shows me the sending message to the receiver so i know i have the context correctly,
and i at first put my broadcast exported to false, but than i thought about permissions problem
so i deleted the exported attribute for being exported=true by default..
bottom line, i see the logs messages but not the toast that the receiver should show me...
if there is any other suggestions i be grateful,
thx
Try creating a different receiver with a different class name. Try using fully qualified class name. Also make sure to change intent action string for a new one. Use something more standard like "testproject.intent.action.LOGGING".
Maybe something got messed up while you were changing receiver properties.
This info from doc is interesting:
android:name
Once you publish your application, you*should not change this name*(unless you've setandroid:exported="false").
Click to expand...
Click to collapse
Regarding "exported" attribute. Safely omit it as it defaults to true automatically when you have intent-filter defined.
And maybe also try Log.d() instead of toast and check logcat.
Log.d
about the Log.d you suggested, when i run even with debug mode from eclipse and install the new module
its require me to restart the phone first, how can i debug like normal application?
when i restart the phone the adb is closed and i loose the debugging ability?
thanks anyway i will try it out...
Use adb logcat from command line.

Is it possible to throw an exception in Xposed hooked method?

Sorry, I can't write in Xposed development thread because I'm new as poster here.
I'm trying to throw an exception in my after hook function, but it doesn't trigger in app that should catch this exception.
For example, I'm trying to throw PackageManager.NameNotFoundException in PackageManager.getPackageInfo(String, int). I forked AndroidEagleEye for easier hook development, disabled all "ignore" try/catches, but my exception isn't triggering my checker app "catch" block anyways.
Code:
@Override
public void after(MethodHookParam param) throws Throwable {
if(mMethod == Methods.getPackageInfo && param.args[0].equals(packageName)){
throw new PackageManager.NameNotFoundException();
}
}
Is throwing an exception through Xposed possible and if it is, how can it be done?
Maybe check and try setThrowable: http://api.xposed.info/reference/de...kParam.html#setThrowable(java.lang.Throwable)
Yeah, it helps, thank you, I shouldn't forget to RTFM.

Categories

Resources