Android可以通過Binder來實現異步通信,實現方式有兩種:一種是通過AIDL(系統會實現onTransact),另一種是:通過自己的實現的onTransact方法來完成通信,其中第一種的還原可以參考之前的博文:Android中Binder安全性和還原逆向中被混淆的AIDL接口。本文講述如何通過自己實現Binder的onTransact完成跨進程通信,可以幫助逆向分析。
服務端:
public class MyService extends Service { private static final String DESCRIPTOR = "MyService"; private final String[] names = {"test1", "test2", "test3", "test4"}; private MyBinder myBinder = new MyBinder(); private class MyBinder extends Binder{ @Override protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { switch (code){ case 0x001: data.enforceInterface(DESCRIPTOR); int num = data.readInt(); reply.writeNoException(); reply.writeString(names[num]); return true; } return super.onTransact(code, data, reply, flags); } } @Override public IBinder onBind(Intent intent) { // TODO: Return the communication channel to the service. return myBinder; } }
可以看到onTransact有四個參數
code , data ,replay , flags
- code 是一個整形的唯一標識,用於區分執行哪個方法,客戶端會傳遞此參數,告訴服務端執行哪個方法;
- data客戶端傳遞過來的參數;
- replay服務器返回回去的值;
- flags標明是否有返回值,0爲有(雙向),1爲沒有(單向)。
客戶端:
public class MainActivity extends AppCompatActivity { private TextView tv = null; private Button button = null; private IBinder binder = null; private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName componentName, IBinder iBinder) { binder = iBinder; } @Override public void onServiceDisconnected(ComponentName componentName) { binder = null; } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv = (TextView)this.findViewById(R.id.tv_info); button = (Button)this.findViewById(R.id.bt_send); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { int num = 2; if(binder != null){ android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); try{ _data.writeInterfaceToken("MyService"); _data.writeInt(num); binder.transact(0x001, _data, _reply, 0); _reply.readException(); tv.setText(_reply.readString()); }catch(RemoteException e){ e.printStackTrace(); }finally { _reply.recycle(); _data.recycle(); } }else{ Toast.makeText(MainActivity.this, "未連接binder service服務。。", Toast.LENGTH_LONG).show(); } } }); Intent intent = new Intent(this, MyService.class); bindService(intent, connection, BIND_AUTO_CREATE); } } |
---|