Xposed 不挂钩方法
Xposed doesn't hook the method
我需要为 Xposed 制作 "Hello world" 应用程序。我试图通过 Xposed 更改 IMEI。它挂钩了一些方法,有些则没有。问题是如何将它们全部挂钩?
我制作了从 TelephonyManager
获取 IMEI 并显示它的测试应用程序:
telephonyManager = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
tv.setText(telephonyManager.getDeviceId());
比我写的方法替换方法:
private void replaceImei(final XC_LoadPackage.LoadPackageParam loadPackageParam,
final String className,
final String methodName)
{
try {
XC_MethodHook.Unhook u =
XposedHelpers.findAndHookMethod(
className,
loadPackageParam.classLoader,
methodName,
new XC_MethodReplacement() {
@Override
protected Object replaceHookedMethod(MethodHookParam methodHookParam) throws Throwable {
XposedBridge.log("happy replaced " + methodHookParam.method.getName()
+ " at " + methodHookParam.method.getDeclaringClass().getName());
return "123456789012345";
}
}
);
if (u != null) {
XposedBridge.log("happy hooked " + u.getHookedMethod().getName() + " "
+ u.getHookedMethod().getDeclaringClass().getCanonicalName());
}
} catch (Exception e) {
XposedBridge.log("happy error " + e.getMessage());
e.printStackTrace();
}
}
并使用它:
@Override
public void handleLoadPackage(final XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
XposedBridge.log("happy loaded app: " + loadPackageParam.packageName);
replaceImei(loadPackageParam,
"android.telephony.TelephonyManager",
"getDeviceId");
}
有效!
但是当我在 Settings
应用程序中查看 IMEI 时,它并没有改变。好的,我获取了 Settings
应用程序的 APK,通过 apktool
提取源并发现以下内容:
.line 86
const-string v1, "imei"
invoke-interface {v0}, Lcom/android/internal/telephony/Phone;->getImei()Ljava/lang/String;
move-result-object v2
invoke-direct {p0, v1, v2}, Lcom/android/settings/deviceinfo/ImeiInformation;->setSummaryText(Ljava/lang/String;Ljava/lang/String;)V
因此,它使用 com.android.internal.telephony.Phone
接口中的 getImei()
方法。因为不可能挂钩接口的方法,所以我找到了 in sources 这个接口的所有实现:
replaceImei(loadPackageParam,
"com.android.internal.telephony.PhoneProxy",
"getImei");
replaceImei(loadPackageParam,
"com.android.internal.telephony.PhoneBase",
"getImei");
replaceImei(loadPackageParam,
"com.android.internal.telephony.gsm.GSMPhone",
"getImei");
replaceImei(loadPackageParam,
"com.android.internal.telephony.imsphone.ImsPhone",
"getImei");
replaceImei(loadPackageParam,
"com.android.internal.telephony.cdma.CDMAPhone",
"getImei");
日志记录了“设置”应用程序 PhoneProxy
中的 getImea()
已挂钩(查看上面的来源):
I/Xposed ( 6800): happy loaded app: com.android.settings
I/Xposed ( 6800): happy hooked getDeviceId android.telephony.TelephonyManager
I/Xposed ( 6800): happy hooked getImei com.android.internal.telephony.PhoneProxy
但没有任何反应,设置中的 IMEI 未更改。当然,我安装了应用程序并在每次迭代时重新启动 phone。
好吧,我试着暴力破解这个任务:我找到了一些其他的方法,也把它们挂了。但这没有帮助。
replaceImei(loadPackageParam,
"com.android.internal.telephony.gsm.GSMPhone",
"getPhoneId");
replaceImei(loadPackageParam,
"com.android.internal.telephony.imsphone.ImsPhone",
"getPhoneId");
replaceImei(loadPackageParam,
"com.android.internal.telephony.cdma.CDMAPhone",
"getPhoneId");
replaceImei(loadPackageParam,
"com.android.internal.telephony.PhoneSubInfoController",
"getDeviceId");
replaceImei(loadPackageParam,
"com.android.internal.telephony.PhoneSubInfoController",
"getImeiForSubscriber");
replaceImei(loadPackageParam,
"com.android.internal.telephony.PhoneSubInfoController",
"getDeviceIdForPhone");
replaceImei(loadPackageParam,
"com.android.internal.telephony.PhoneSubInfo",
"getDeviceId");
replaceImei(loadPackageParam,
"com.android.internal.telephony.PhoneSubInfo",
"getImei");
replaceImei(loadPackageParam,
"com.android.internal.telephony.PhoneSubInfoProxy",
"getImeiForSubscriber");
replaceImei(loadPackageParam,
"com.android.internal.telephony.PhoneSubInfoProxy",
"getImei");
replaceImei(loadPackageParam,
"com.android.internal.telephony.PhoneBase",
"getPhoneId");
有什么想法吗?怎么了?怎么办?
所有实验均在 Nexus 4 上进行 Android 5.1.1.
这个问题的完整来源在这里:https://gist.github.com/tseglevskiy/d100898468b286e1fff214778c9609b3
更新 1
实验的下一部分。我发现可以通过实现 IXposedHookZygoteInit
接口来 hook Zygote 早期阶段的一些方法。好的,我做到了:
private void replaceImeiInitZygote(final String className,
final String methodName)
{
try {
final Class<?> foundClass = XposedHelpers.findClass(className, null);
if (foundClass != null) {
XC_MethodHook.Unhook u = XposedHelpers.findAndHookMethod(foundClass, methodName,
new XC_MethodReplacement() {
@Override
protected Object replaceHookedMethod(MethodHookParam methodHookParam) throws Throwable {
XposedBridge.log("happy replaced " + methodHookParam.method.getName()
+ " at " + methodHookParam.method.getDeclaringClass().getName());
return "123456789099999";
}
});
if (u != null) {
XposedBridge.log("happy hooked from initZygote " + u.getHookedMethod().getName() + " "
+ u.getHookedMethod().getDeclaringClass().getCanonicalName());
}
}
} catch (Exception e) {
XposedBridge.log("happy error " + e.getMessage());
e.printStackTrace();
}
}
并使用它:
@Override
public void initZygote(StartupParam startupParam) throws Throwable {
replaceImeiInitZygote(
"android.telephony.TelephonyManager",
"getDeviceId");
replaceImeiInitZygote(
"com.android.internal.telephony.PhoneProxy",
"getImei");
replaceImeiInitZygote(
"com.android.internal.telephony.PhoneBase",
"getImei");
replaceImeiInitZygote(
"com.android.internal.telephony.gsm.GSMPhone",
"getImei");
replaceImeiInitZygote(
"com.android.internal.telephony.imsphone.ImsPhone",
"getImei");
replaceImeiInitZygote(
"com.android.internal.telephony.cdma.CDMAPhone",
"getImei");
}
通过日志它挂钩了几个方法:
I/Xposed ( 198): happy hooked from initZygote getDeviceId android.telephony.TelephonyManager
I/Xposed ( 198): happy hooked from initZygote getImei com.android.internal.telephony.PhoneProxy
但 id 也不会在“设置”应用中更改 IMEI。怎么了?
好吧,你几乎做到了!您试图挂钩 getImei(),但实际上它从未被系统调用。请改用 getDeviceId(),它 returns 相同的数据。
要在设置中更改 IMEI,试试这个代码片段,它非常有效:
findAndHookMethod(
"com.android.internal.telephony.gsm.GSMPhone",
lpparam.classLoader,
"getDeviceId",
new XC_MethodReplacement() {
@Override
protected Object replaceHookedMethod(MethodHookParam param) throws Throwable {
XposedBridge.log("NEW IMEI!!! com.android.internal.telephony.gsm.GSMPhone.getDeviceId()");
return "111111111111111";
}
}
);
顺便说一下,你也可以 hook 这些方法:
com.android.internal.telephony.PhoneSubInfo.getDeviceId()
com.android.internal.telephony.gsm.GSMPhone.getDeviceId()
com.android.internal.telephony.cdma.CDMAPhone.getDeviceId()
com.android.internal.telephony.imsphone.ImsPhone.getDeviceId()
com.android.internal.telephony.sip.SipPhone.getDeviceId()
干杯!
我需要为 Xposed 制作 "Hello world" 应用程序。我试图通过 Xposed 更改 IMEI。它挂钩了一些方法,有些则没有。问题是如何将它们全部挂钩?
我制作了从 TelephonyManager
获取 IMEI 并显示它的测试应用程序:
telephonyManager = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
tv.setText(telephonyManager.getDeviceId());
比我写的方法替换方法:
private void replaceImei(final XC_LoadPackage.LoadPackageParam loadPackageParam,
final String className,
final String methodName)
{
try {
XC_MethodHook.Unhook u =
XposedHelpers.findAndHookMethod(
className,
loadPackageParam.classLoader,
methodName,
new XC_MethodReplacement() {
@Override
protected Object replaceHookedMethod(MethodHookParam methodHookParam) throws Throwable {
XposedBridge.log("happy replaced " + methodHookParam.method.getName()
+ " at " + methodHookParam.method.getDeclaringClass().getName());
return "123456789012345";
}
}
);
if (u != null) {
XposedBridge.log("happy hooked " + u.getHookedMethod().getName() + " "
+ u.getHookedMethod().getDeclaringClass().getCanonicalName());
}
} catch (Exception e) {
XposedBridge.log("happy error " + e.getMessage());
e.printStackTrace();
}
}
并使用它:
@Override
public void handleLoadPackage(final XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
XposedBridge.log("happy loaded app: " + loadPackageParam.packageName);
replaceImei(loadPackageParam,
"android.telephony.TelephonyManager",
"getDeviceId");
}
有效!
但是当我在 Settings
应用程序中查看 IMEI 时,它并没有改变。好的,我获取了 Settings
应用程序的 APK,通过 apktool
提取源并发现以下内容:
.line 86
const-string v1, "imei"
invoke-interface {v0}, Lcom/android/internal/telephony/Phone;->getImei()Ljava/lang/String;
move-result-object v2
invoke-direct {p0, v1, v2}, Lcom/android/settings/deviceinfo/ImeiInformation;->setSummaryText(Ljava/lang/String;Ljava/lang/String;)V
因此,它使用 com.android.internal.telephony.Phone
接口中的 getImei()
方法。因为不可能挂钩接口的方法,所以我找到了 in sources 这个接口的所有实现:
replaceImei(loadPackageParam,
"com.android.internal.telephony.PhoneProxy",
"getImei");
replaceImei(loadPackageParam,
"com.android.internal.telephony.PhoneBase",
"getImei");
replaceImei(loadPackageParam,
"com.android.internal.telephony.gsm.GSMPhone",
"getImei");
replaceImei(loadPackageParam,
"com.android.internal.telephony.imsphone.ImsPhone",
"getImei");
replaceImei(loadPackageParam,
"com.android.internal.telephony.cdma.CDMAPhone",
"getImei");
日志记录了“设置”应用程序 PhoneProxy
中的 getImea()
已挂钩(查看上面的来源):
I/Xposed ( 6800): happy loaded app: com.android.settings
I/Xposed ( 6800): happy hooked getDeviceId android.telephony.TelephonyManager
I/Xposed ( 6800): happy hooked getImei com.android.internal.telephony.PhoneProxy
但没有任何反应,设置中的 IMEI 未更改。当然,我安装了应用程序并在每次迭代时重新启动 phone。
好吧,我试着暴力破解这个任务:我找到了一些其他的方法,也把它们挂了。但这没有帮助。
replaceImei(loadPackageParam,
"com.android.internal.telephony.gsm.GSMPhone",
"getPhoneId");
replaceImei(loadPackageParam,
"com.android.internal.telephony.imsphone.ImsPhone",
"getPhoneId");
replaceImei(loadPackageParam,
"com.android.internal.telephony.cdma.CDMAPhone",
"getPhoneId");
replaceImei(loadPackageParam,
"com.android.internal.telephony.PhoneSubInfoController",
"getDeviceId");
replaceImei(loadPackageParam,
"com.android.internal.telephony.PhoneSubInfoController",
"getImeiForSubscriber");
replaceImei(loadPackageParam,
"com.android.internal.telephony.PhoneSubInfoController",
"getDeviceIdForPhone");
replaceImei(loadPackageParam,
"com.android.internal.telephony.PhoneSubInfo",
"getDeviceId");
replaceImei(loadPackageParam,
"com.android.internal.telephony.PhoneSubInfo",
"getImei");
replaceImei(loadPackageParam,
"com.android.internal.telephony.PhoneSubInfoProxy",
"getImeiForSubscriber");
replaceImei(loadPackageParam,
"com.android.internal.telephony.PhoneSubInfoProxy",
"getImei");
replaceImei(loadPackageParam,
"com.android.internal.telephony.PhoneBase",
"getPhoneId");
有什么想法吗?怎么了?怎么办?
所有实验均在 Nexus 4 上进行 Android 5.1.1.
这个问题的完整来源在这里:https://gist.github.com/tseglevskiy/d100898468b286e1fff214778c9609b3
更新 1
实验的下一部分。我发现可以通过实现 IXposedHookZygoteInit
接口来 hook Zygote 早期阶段的一些方法。好的,我做到了:
private void replaceImeiInitZygote(final String className,
final String methodName)
{
try {
final Class<?> foundClass = XposedHelpers.findClass(className, null);
if (foundClass != null) {
XC_MethodHook.Unhook u = XposedHelpers.findAndHookMethod(foundClass, methodName,
new XC_MethodReplacement() {
@Override
protected Object replaceHookedMethod(MethodHookParam methodHookParam) throws Throwable {
XposedBridge.log("happy replaced " + methodHookParam.method.getName()
+ " at " + methodHookParam.method.getDeclaringClass().getName());
return "123456789099999";
}
});
if (u != null) {
XposedBridge.log("happy hooked from initZygote " + u.getHookedMethod().getName() + " "
+ u.getHookedMethod().getDeclaringClass().getCanonicalName());
}
}
} catch (Exception e) {
XposedBridge.log("happy error " + e.getMessage());
e.printStackTrace();
}
}
并使用它:
@Override
public void initZygote(StartupParam startupParam) throws Throwable {
replaceImeiInitZygote(
"android.telephony.TelephonyManager",
"getDeviceId");
replaceImeiInitZygote(
"com.android.internal.telephony.PhoneProxy",
"getImei");
replaceImeiInitZygote(
"com.android.internal.telephony.PhoneBase",
"getImei");
replaceImeiInitZygote(
"com.android.internal.telephony.gsm.GSMPhone",
"getImei");
replaceImeiInitZygote(
"com.android.internal.telephony.imsphone.ImsPhone",
"getImei");
replaceImeiInitZygote(
"com.android.internal.telephony.cdma.CDMAPhone",
"getImei");
}
通过日志它挂钩了几个方法:
I/Xposed ( 198): happy hooked from initZygote getDeviceId android.telephony.TelephonyManager
I/Xposed ( 198): happy hooked from initZygote getImei com.android.internal.telephony.PhoneProxy
但 id 也不会在“设置”应用中更改 IMEI。怎么了?
好吧,你几乎做到了!您试图挂钩 getImei(),但实际上它从未被系统调用。请改用 getDeviceId(),它 returns 相同的数据。
要在设置中更改 IMEI,试试这个代码片段,它非常有效:
findAndHookMethod(
"com.android.internal.telephony.gsm.GSMPhone",
lpparam.classLoader,
"getDeviceId",
new XC_MethodReplacement() {
@Override
protected Object replaceHookedMethod(MethodHookParam param) throws Throwable {
XposedBridge.log("NEW IMEI!!! com.android.internal.telephony.gsm.GSMPhone.getDeviceId()");
return "111111111111111";
}
}
);
顺便说一下,你也可以 hook 这些方法:
com.android.internal.telephony.PhoneSubInfo.getDeviceId()
com.android.internal.telephony.gsm.GSMPhone.getDeviceId()
com.android.internal.telephony.cdma.CDMAPhone.getDeviceId()
com.android.internal.telephony.imsphone.ImsPhone.getDeviceId()
com.android.internal.telephony.sip.SipPhone.getDeviceId()
干杯!