Android. Hook framework xposed

Source: Internet
Author: User

Android. Hook framework xposed

Tutorial: https://github.com/rovo89/XposedBridge/wiki/Development-tutorial

Official Website: http://repo.xposed.info/module/de.robv.android.xposed.installer

Apk: http://dl-xda.xposed.info/modules/de.robv.android.xposed.installer_v33_36570c.apk

Source code: https://github.com/rovo89/XposedInstaller

Basic module development process

1. Create a project android4.0.3 (api15, other versions are also available in the test). You do not need to use the activity.

2. Modify AndroidManifest. xml

<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="de.robv.android.xposed.mods.tutorial"    android:versionCode="1"    android:versionName="1.0" >    <uses-sdk android:minSdkVersion="15" />    <application        android:icon="@drawable/ic_launcher"        android:label="@string/app_name" >        <meta-data            android:name="xposedmodule"            android:value="true" />        <meta-data            android:name="xposeddescription"            android:value="Easy example" />        <meta-data            android:name="xposedminversion"            android:value="54" />    </application></manifest>

3. Create a new lib folder under the project directory and put the downloaded XposedBridgeApi-54.jar package into it.

Eclipse right-click the XposedBridgeApi-54.jar in the project-Build Path-Add to Build Path.

Right-click the project and select Open Module Settings. In the displayed window, Open the Dependencies tab. Change the Scope attribute after the jar package XposedBridgeApi to provided.

4. module implementation Interface

package de.robv.android.xposed.mods.tutorial; import de.robv.android.xposed.IXposedHookLoadPackage;import de.robv.android.xposed.XposedBridge;import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam; public class Tutorial implements IXposedHookLoadPackage {    public void handleLoadPackage(final LoadPackageParam lpparam) throws Throwable {        XposedBridge.log("Loaded app: " + lpparam.packageName);    }}

5. Entry assets/xposed_init configuration, declare the entry class to be loaded to XposedInstaller:

#! Javade. robv. android. xposed. Mod. tutorial. Tutorial // complete Class Name: package name + class name

6. Locate the api to be hooked

Decompile the target program and view the Smali Code directly in AOSP (android source code ).

7. XposedBridge to hook it

Specify the package name to be hooked to determine whether the currently loaded package is a specified package. specify the method name to be hooked to implement beforeHookedMethod and afterHookedMethod.

Example:

package de.robv.android.xposed.mods.tutorial; import static de.robv.android.xposed.XposedHelpers.findAndHookMethod; import de.robv.android.xposed.IXposedHookLoadPackage; import de.robv.android.xposed.XC\_MethodHook; import de.robv.android.xposed.callbacks.XC\_LoadPackage.LoadPackageParam; public class Tutorial implements IXposedHookLoadPackage { public void handleLoadPackage(final LoadPackageParam lpparam) throws Throwable { if (!lpparam.packageName.equals("com.android.systemui")) return;         findAndHookMethod("com.android.systemui.statusbar.policy.Clock", lpparam.classLoader, "updateClock", new XC_MethodHook() {            @Override            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {                // this will be called before the clock was updated by the original method            }            @Override            protected void afterHookedMethod(MethodHookParam param) throws Throwable {                // this will be called after the clock was updated by the original method            }    });    }  }

Override the two methods beforeHookedMethod and afterHookedMethod of XC_MethodHook. These two methods will be executed before and after the original method. you can use the beforeHookedMethod method to print/tamper with the parameters of the method call (through param. args), or even block calling the original method (send your own results ). the afterHookedMethod method can be used to perform the result based on the original method. you can also use it to manipulate the results. of course, you can add your own code, which will be executed accurately before or after the original method.

Key APIs

IXposedHookLoadPackage

HandleLoadPackage: This method is used to perform user operations when loading the application package.

Call example

public class XposedInterface implements IXposedHookLoadPackage {public void handleLoadPackage(final LoadPackageParam lpparam) throws Throwable {XposedBridge.log("Kevin-Loaded app: " + lpparam.packageName); }}

Parameter description | final LoadPackageParam lpparam contains some basic information about the loaded application.

XposedHelpers

FindAndHookMethod; this is an auxiliary method, which can be statically imported as follows:

#!javaimport static de.robv.android.xposed.XposedHelpers.findAndHookMethod;

Example

findAndHookMethod("com.android.systemui.statusbar.policy.Clock", lpparam.classLoader, "handleUpdateClock", new XC_MethodHook() {@Overrideprotected void beforeHookedMethod(MethodHookParam param) throws Throwable {// this will be called before the clock was updated by the original method }@Overrideprotected void afterHookedMethod(MethodHookParam param) throws Throwable {// this will be called after the clock was updated by the original method }});

Parameter description

FindAndHookMethod (Class <?> Clazz, // ClassLoader of the class to be hooked, // ClassLoader of the Class Loader, which can be set to null String methodName, // name of the method to be hooked Object... parameterTypesAndCallback

The last parameter set of the function, including:

(1) parameters of the target method of the Hook, for example:

"com.android.internal.policy.impl.PhoneWindow.DecorView"

Is the parameter class of the method.

(2) callback method:

a.XC_MethodHook b.XC_MethodReplacement
Details of module development

1. the Dalvik incubator Zygote (in the Android system, all application processes and system service processes SystemServer are generated by the Zygote process/fork) process corresponds to the Program/system/bin/app_process. what really works in the Xposed framework is the method hook.

#! Java, because Xposed works by replacing files in the/system/bin directory, the root permission is required during install, but the root permission is not required during running.

2. Unified log management, tag display package name

#!java    Log.d(MYTAG+lpparam.packageName, "hello" + lpparam.packageName);

3. implant a broadcast receiver to dynamically execute commands

findAndHookMethod("android.app.Application", lpparam.classLoader, "onCreate", new XC_MethodHook() {    @Override    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {         Context context = (Context) param.thisObject;        IntentFilter filter = new IntentFilter(myCast.myAction);        filter.addAction(myCast.myCmd);        context.registerReceiver(new myCast(), filter);     }     @Override    protected void afterHookedMethod(MethodHookParam param) throws Throwable {        super.afterHookedMethod(param);    }});

4. Get context

#!java    fristApplication = (Application) param.thisObject;

5. Select the application oncreate program as the injection point to start the function but the onCreate method of MainActivity (this class may be overwritten, so the oncreate method is obtained through reflection)

String appClassName = this.getAppInfo().className;        if (appClassName == null) {            Method hookOncreateMethod = null;            try {                hookOncreateMethod = Application.class.getDeclaredMethod("onCreate", new Class[] {});            } catch (NoSuchMethodException e) {                e.printStackTrace();            }            hookhelper.hookMethod(hookOncreateMethod, new ApplicationOnCreateHook());

6. Exclude the system app, exclude itself, and determine the main thread.

if(lpparam.appInfo == null ||                 (lpparam.appInfo.flags & (ApplicationInfo.FLAG_SYSTEM | ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) !=0){            return;        }else if(lpparam.isFirstApplication && !ZJDROID_PACKAGENAME.equals(lpparam.packageName)){

7. hook method

Only methods and constructors can be hooked, Cannot hook interfaces, and Cannot hook abstract methods can Only hook methods and constructor methods, but Cannot hook interfaces and non-abstract methods in abstract classes, methods In the interface cannot be hooked (the method in the interface is public abstract by default. field must be public static final)

8. Custom classes are included in the parameters.

Public void myMethod (String a, MyClass B) Get the custom class through reflection, you can also use the [xposedhelpers] (https://github.com/rovo89/XposedBridge/wiki/Helpers#class-xposedhelpers) encapsulated method findMethod/findConstructor/callStaticMethod ....

9. Reflection of custom classes after injection

Class<?> hookMessageListenerClass = null; hookMessageListenerClass = lpparam.classLoader.loadClass("org.jivesoftware.smack.MessageListener"); findAndHookMethod("org.jivesoftware.smack.ChatManager", lpparam.classLoader, "createChat", String.class , hookMessageListenerClass ,new XC_MethodHook() {    @Override    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {         String sendTo = (String) param.args[0];        Log.i(tag , "sendTo : + " + sendTo );     }     @Override    protected void afterHookedMethod(MethodHookParam param) throws Throwable {        super.afterHookedMethod(param);    }});

10. hook the method of a class, which is a subclass and does not overwrite the parent class. In this case, hook the parent class or subclass. (After the hook parent class method, if the subclass is not overwritten, it will take effect. the subclass Rewriting Method requires another hook) (if the subclass overrides the parent class method with spuer, the hook parent class is still valid)

For example, java.net. HttpURLConnection extends URLConnection,

Method in parent class

public OutputStream getOutputStream() throws IOException {           throw new UnknownServiceException("protocol doesn't support output");       }  org.apache.http.impl.client.AbstractHttpClient extends CloseableHttpClient ,

The method is in the parent class (note that the inherited javasacthttpclient implements org. apache. http. client. HttpClient) of android)

Public CloseableHttpResponse execute (final HttpHost target, final HttpRequest request, final HttpContext context) throws IOException, ClientProtocolException {return doExecute (target, request, context);} android. async. http rewrite HttpGet causes zjdroid hook org. apache. http. impl. client. abstractHttpClient execute cannot obtain the request url and method

11. hook Constructor

public static XC_MethodHook.Unhook findAndHookConstructor(String className, ClassLoader classLoader, Object... parameterTypesAndCallback) {    return findAndHookConstructor(findClass(className, classLoader), parameterTypesAndCallback);}

12. 4. The onCreate method of the application is overwritten, such as the Alibaba shell, and rewritten as the native method.

Solution 1: reflect to the onCreate method after the application class is overwritten and then hook the method.

Solution 2: hook Constructor (constructor is overwritten, continue solution 1)

13. The native method can be used to hook, but not to hook the dynamic link library during java-layer calls.

Hook possible HTTP requests in android

First, determine the http request api, which is roughly divided:

HttpClient provided by apache 1) Create HttpClient, GetMethod, PostMethod, HttpRequest, and other objects; 2) set connection parameters; 3) execute HTTP operations; 4) process server return results. httpURLConnection provided by java 1) Create URL and URLConnection/HttpURLConnection object 2) set connection parameters 3) connect to server 4) write data to Server 5) third-party library of webview provided by android: volley/android-async-http/xutils (essentially an extension of the first two methods, method rewriting may affect the subsequent hooks)

Before learning about java hooks, You can first look at the basic code HttpClient and basic use of HttpURLConnection.

For the HttpClient hook, refer to the Zjdroid of Jia Zhijun Daniel

Method executeRequest = RefInvoke.findMethodExact("org.apache.http.impl.client.AbstractHttpClient", ClassLoader.getSystemClassLoader(),        "execute", HttpHost.class, HttpRequest.class, HttpContext.class); hookhelper.hookMethod(executeRequest, new AbstractBahaviorHookCallBack() {    @Override    public void descParam(HookParam param) {        // TODO Auto-generated method stub        Logger.log_behavior("Apache Connect to URL ->");        HttpHost host = (HttpHost) param.args[0];         HttpRequest request = (HttpRequest) param.args[1];        if (request instanceof org.apache.http.client.methods.HttpGet) {            org.apache.http.client.methods.HttpGet httpGet = (org.apache.http.client.methods.HttpGet) request;            Logger.log_behavior("HTTP Method : " + httpGet.getMethod());            Logger.log_behavior("HTTP GET URL : " + httpGet.getURI().toString());            Header[] headers = request.getAllHeaders();            if (headers != null) {                for (int i = 0; i < headers.length; i++) {                    Logger.log_behavior(headers[i].getName() + ":" + headers[i].getName());                }            }        } else if (request instanceof HttpPost) {            HttpPost httpPost = (HttpPost) request;            Logger.log_behavior("HTTP Method : " + httpPost.getMethod());            Logger.log_behavior("HTTP URL : " + httpPost.getURI().toString());            Header[] headers = request.getAllHeaders();            if (headers != null) {                for (int i = 0; i < headers.length; i++) {                    Logger.log_behavior(headers[i].getName() + ":" + headers[i].getValue());                }            }            HttpEntity entity = httpPost.getEntity();            String contentType = null;            if (entity.getContentType() != null) {                contentType = entity.getContentType().getValue();                if (URLEncodedUtils.CONTENT_TYPE.equals(contentType)) {                     try {                        byte[] data = new byte[(int) entity.getContentLength()];                        entity.getContent().read(data);                        String content = new String(data, HTTP.DEFAULT_CONTENT_CHARSET);                        Logger.log_behavior("HTTP POST Content : " + content);                    } catch (IllegalStateException e) {                        // TODO Auto-generated catch block                        e.printStackTrace();                    } catch (IOException e) {                        // TODO Auto-generated catch block                        e.printStackTrace();                    }                 } else if (contentType.startsWith(HTTP.DEFAULT_CONTENT_TYPE)) {                    try {                        byte[] data = new byte[(int) entity.getContentLength()];                        entity.getContent().read(data);                        String content = new String(data, contentType.substring(contentType.lastIndexOf("=") + 1));                        Logger.log_behavior("HTTP POST Content : " + content);                    } catch (IllegalStateException e) {                        // TODO Auto-generated catch block                        e.printStackTrace();                    } catch (IOException e) {                        // TODO Auto-generated catch block                        e.printStackTrace();                    }                 }            }else{                byte[] data = new byte[(int) entity.getContentLength()];                try {                    entity.getContent().read(data);                    String content = new String(data, HTTP.DEFAULT_CONTENT_CHARSET);                    Logger.log_behavior("HTTP POST Content : " + content);                } catch (IllegalStateException e) {                    // TODO Auto-generated catch block                    e.printStackTrace();                } catch (IOException e) {                    // TODO Auto-generated catch block                    e.printStackTrace();                }             }         }    }     @Override    public void afterHookedMethod(HookParam param) {        // TODO Auto-generated method stub        super.afterHookedMethod(param);        HttpResponse resp = (HttpResponse) param.getResult();        if (resp != null) {            Logger.log_behavior("Status Code = " + resp.getStatusLine().getStatusCode());            Header[] headers = resp.getAllHeaders();            if (headers != null) {                for (int i = 0; i < headers.length; i++) {                    Logger.log_behavior(headers[i].getName() + ":" + headers[i].getValue());                }            }         }    }});

The hook Zjdroid of HttpURLConnection fails to provide a perfect solution. To obtain data fields other than URLs, you must perform operations on the I/O Stream.

Method openConnectionMethod = RefInvoke.findMethodExact("java.net.URL", ClassLoader.getSystemClassLoader(), "openConnection");hookhelper.hookMethod(openConnectionMethod, new AbstractBahaviorHookCallBack() {    @Override    public void descParam(HookParam param) {        // TODO Auto-generated method stub        URL url = (URL) param.thisObject;        Logger.log_behavior("Connect to URL ->");        Logger.log_behavior("The URL = " + url.toString());    }});

The temporary solution I adopted is to perform regular match on I/O, print out the data field similar to the url, and the code is as follows (this code can only solve the preceding HttpUtils and has a false positive, if you have any good ideas, please give me some advice)

findAndHookMethod("java.io.PrintWriter", lpparam.classLoader, "print",String.class, new XC_MethodHook() {    @Override    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {        String print = (String) param.args[0];        Pattern pattern = Pattern.compile("(\\w+=.*)");        Matcher matcher = pattern.matcher(print);        if (matcher.matches())            Log.i(tag+lpparam.packageName,"data : " + print);        //Log.d(tag,"A :" + print);    } });

Zjdroidhook fails because the Android-async-http rewrite of HttpGet (the interpretation of HttpGet and HttpPost is not entered). This problem can be solved by adding an else statement.

else {                    HttpEntityEnclosingRequestBase httpGet = (HttpEntityEnclosingRequestBase) request;                    HttpEntity entity = httpGet.getEntity();                    Logger.log_behavior("HttpRequestBase URL : " + httpGet.getURI().toString());                    Header[] headers = request.getAllHeaders();                    if (headers != null) {                        for (int i = 0; i < headers.length; i++) {                            Logger.log_behavior(headers[i].getName() + ":" + headers[i].getName());                        }                    }                     if(entity!= null){                                try {                                    String content = EntityUtils                                            .toString(entity);                                    Logger.log_behavior("HTTP entity Content : "                                            + content);                                } catch (IllegalStateException e) {                                    // TODO Auto-generated catch block                                    e.printStackTrace();                                } catch (IOException e) {                                    // TODO Auto-generated catch block                                    e.printStackTrace();                                }                    }                     }
Some common tools Zjdroid: Shelling/api monitoring justTrustMe: Ignore Certificate Validation IntentMonitor: monitor explicit/hidden intent intentXinstaller: Set Application/device properties... XPrivacy: permission management

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.