Binder Proxy technical solution, binderproxy
Binder Proxy technical solution
Author's low-end coders
Time:
0x0
Several friends tried to hook the ioctl of system_process to intercept the IPC communication of the system. The disadvantage of this solution is that it is too low-layer. After successful interception, it is quite troublesome to parse the communication data. in addition, there are also a bunch of compatibility issues. Due to different Android firmware versions, some Parcelable structure fields are changed. If these changes are resolved in ioctl, all of them need to be taken into account one by one, so I think there is still a gap between this solution and productization.
0x1
On Android, NativeService of all systems is mainly stored in the system_process and com. android. phone processes. For example, we often see ActivityManagerService (AMS ). Most of these NativeService are Java objects inherited from the Binder.
We know that most of IPC communication on Android is implemented through its unique binder module. Therefore, the above Java NativeService needs to communicate with the kernel, because only c/c ++ can directly interact with the kernel, there must be JNI communication. For example, the design of AMS:
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, which is the Java object we implement ), binder Proxy can be implemented. The following is:
0x2
In the Java layer, to obtain the AMS reference, use ServiceManager. However, this class is hidden class and can be called only through reflection. You can obtain AMS through ServiceManager. getService ("activity.
In Native, to obtain the JavaBBinder address corresponding to AMS, The getService method of defaservicservicemanager gets the address.
The next step is to replace the mObject object. The mObject object of JavaBBinder 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;};
0x3
Because BinderProxy has a high level of interception, It is very convenient to parse the request data structure. Most of the interfaces used are Framework interfaces, and the compatibility does not exist. Below is an example I wrote, the example mainly shows how to prevent a pkg from being killed:
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; static {if (ReflecterHelper. setClass (CLASS_NAME) {s_broadcastIntent_code = ReflecterHelper. getStaticIntValue ("BROADCAST_INTENT_TRAN SACTION ",-1);} else {s_broadcastIntent_code =-1 ;}} private IBinder mBinder; public ProxyActivityManagerServcie (IBinder binder) {mBinder = binder; mResorter = new SmsReceiverResorter (binder) ;}@ Override protected boolean onTransact (int code, Parcel data, Parcel reply, int flags) throws RemoteException {/***** public int broadcastIntent (IApplicationThread caller, * Intent intent, String re SolvedType, IIntentReceiver resulcode, * int resultCode, String resultData, Bundle map, * String requiredPermission, int appOp, boolean serialized, * boolean sticky, int userId) throws RemoteException */if (code = s_broadcastIntent_code) {pos = data. dataposition (); data. enforceInterface (DESCRIPTOR); IBinder caller = data. readStrongBinder (); Intent intent = Intent. CREATOR. createFromParcel (data ); String resolvedType = data. readString (); IBinder resultasks = data. readStrongBinder (); int resultCode = data. readInt (); String resultData = data. readString (); Bundle map = data. readBundle (); String requiredPermission = data. readString (); int appOp = data. readInt (); boolean serialized = data. readInt ()! = 0; boolean sticky = data. readInt ()! = 0; int userId = data. readInt (); // TODO obtains all the parameters and intercepts them according to the parameters. // FINAL data. setDataPosition (pos);} return mBinder. transact (code, data, reply, flags );}}
0x4
This technical solution involves injection and dex loading. There are a lot of online tutorials in this regard. For so injection, refer to LibInject of the great god of the river. For Java injection, refer to malokch's injection of Android processes, and hook the java World method.
In addition, you can also refer to my previous series of articles "Attacking Android injection". This series details the full technical details of so injection and dex injection into the binder proxy.
Sample source code I have uploaded to https://github.com/boyliang/Hijack_AMS_broadIntent
Android
Someone asked you something similar to yours.
People are following the mistakes you posted.
At com. android. server. UsbObserver. init (UsbObserver. java: 131)
At com. android. server. UsbObserver. <init> (UsbObserver. java: 65)
At com. android. server. ServerThread. run (SystemServer. java: 402)
Cocould not open GPS configuration file/etc/gps. conf
Executing/system/bin/tc failed: No such file or directory
Executing/system/bin/tc failed: No such file or directory
Executing/system/bin/tc failed: No such file or directory
Someone suggested changing the read and write permissions of the underlying file. You can give it a try.
Link to references.
Reference: zhidao.baidu.com/question/396665672.html
Android error message
First, you can see that you lack a person file. You can check the version of your simulator and whether you have added sdcard. There is also a lack of permissions: java. lang. SecurityException, this application may have a relatively low sdk version during development, and the current Simulator version is relatively high, enhancing permission control. Cannot start volume '/sdcard' (volume is not bound) does not seem to have sdcard, and the sound file Cannot be found: Couldn't open fd for content: // settings/system/icationication_sound
Naturally, media player cannot be started. Check it.