2015-12-03 2 views
1

Maintenant, je suis en train de tester quelque chose dans le cryptage des appels téléphoniques Android. J'Accrocher une méthode dans RIL.java en utilisant le cadre XposedAndroid RIL socket et le cryptage des appels téléphoniques?

if (lpparam.packageName.contains("com.android.phone")){ 
    XposedBridge.log("damowang Loaded app: " + lpparam.packageName); 

    findAndHookMethod("com.android.internal.telephony.RIL", lpparam.classLoader, "readRilMessage",InputStream.class,byte[].class,new XC_MethodHook() { 
      @Override 
      protected void beforeHookedMethod(MethodHookParam param) throws Throwable { 
      } 
      @Override 
      protected void afterHookedMethod(MethodHookParam param) throws Throwable { 
      int messageLenth = Integer.parseInt(param.getResult().toString()); 
      XposedBridge.log("damowang : RILSender readRilMessage result==="+messageLenth); 
      byte[] arr = (byte[])param.args[1]; 

      String byteStr = ""; 
      for(int i=0;i<messageLenth;i++){ 
       byteStr += arr[i]; 
       byteStr += " "; 
      } 
      XposedBridge.log("damowang : RILSender readRilMessage byte[]==="+byteStr); 
      } 
    }); 
    findAndHookMethod("com.android.internal.telephony.RIL", lpparam.classLoader, "invokeOemRilRequestRaw",byte[].class,Message.class,new XC_MethodHook() { 
      @Override 
      protected void beforeHookedMethod(MethodHookParam param) throws Throwable { 
      } 
      @Override 
      protected void afterHookedMethod(MethodHookParam param) throws Throwable { 
       XposedBridge.log("damowang : RIL invokeOemRilRequestRaw result==="); 
       byte[] arr = (byte[])param.args[0]; 
       String byteStr = ""; 
       for(int i=0;i<arr.length;i++){ 
        byteStr += arr[i]; 
        byteStr += " "; 
        } 
       XposedBridge.log("damowang : RIL invokeOemRilRequestRaw byte[]==="+arr.length+"==="+"==="+byteStr); 
      } 
    }); 
} 

Je suis arrivé quelques journaux comme:

damowang : RIL invokeOemRilRequestRaw byte[]===5======11 24 0 5 1 
damowang : RIL invokeOemRilRequestRaw byte[]===5======11 24 0 5 0 
damowang : RILSender readRilMessage result===12 
damowang : RILSender readRilMessage byte[]===0 0 0 0 -95 0 0 0 17 0 0 0 
damowang : RILSender readRilMessage result===12 
damowang : RILSender readRilMessage byte[]===0 0 0 0 -94 0 0 0 17 0 0 0 
damowang : RILSender readRilMessage result===8 
damowang : RILSender readRilMessage byte[]===1 0 0 0 -22 3 0 0 
damowang : RILSender readRilMessage result===60 
damowang : RILSender readRilMessage byte[]===1 0 0 0 -15 3 0 0 16 0 0 0 99 4 0 0 16 0 0 0 -56 0 0 0 16 0 0 0 -56 0 0 0 -1 -1 -1 -1 99 0 0 0 -1 -1 -1 127 -1 -1 -1 127 -1 -1 -1 127 -1 -1 -1 127 -1 -1 -1 127 

Mais ces octets ne peuvent pas par CAST pour cordes de sens, qu'est-ce que ces octets [] signifier? (peut-être contient une commande AT?) comment puis-je utiliser Xposed pour accrocher les threads émetteur et récepteur dans RIL.java?

class RILSender extends Handler implements Runnable { 
    public RILSender(Looper looper) { 
     super(looper); 
    } 
    // Only allocated once 
    byte[] dataLength = new byte[4]; 
    //***** Runnable implementation 
    public void 
    run() { 
     //setup if needed 
    } 
    //***** Handler implementation 
    @Override public void 
    handleMessage(Message msg) { 
     RILRequest rr = (RILRequest)(msg.obj); 
     RILRequest req = null; 
     switch (msg.what) { 
      case EVENT_SEND: 
       /** 
       * mRequestMessagePending++ already happened for every 
       * EVENT_SEND, thus we must make sure 
       * mRequestMessagePending-- happens once and only once 
       */ 
       boolean alreadySubtracted = false; 
       try { 
        LocalSocket s; 
        s = mSocket; 
        if (s == null) { 
         rr.onError(RADIO_NOT_AVAILABLE, null); 
         rr.release(); 
         if (mRequestMessagesPending > 0) 
          mRequestMessagesPending--; 
         alreadySubtracted = true; 
         return; 
        } 
        synchronized (mRequestList) { 
         mRequestList.add(rr); 
         mRequestMessagesWaiting++; 
        } 
        if (mRequestMessagesPending > 0) 
         mRequestMessagesPending--; 
        alreadySubtracted = true; 
        byte[] data; 
        data = rr.mp.marshall(); 
        rr.mp.recycle(); 
        rr.mp = null; 
        if (data.length > RIL_MAX_COMMAND_BYTES) { 
         throw new RuntimeException(
           "Parcel larger than max bytes allowed! " 
                 + data.length); 
        } 
        // parcel length in big endian 
        dataLength[0] = dataLength[1] = 0; 
        dataLength[2] = (byte)((data.length >> 8) & 0xff); 
        dataLength[3] = (byte)((data.length) & 0xff); 
        //Rlog.v(LOG_TAG, "writing packet: " + data.length + " bytes"); 
        s.getOutputStream().write(dataLength); 
        s.getOutputStream().write(data); 
       } catch (IOException ex) { 
        Rlog.e(LOG_TAG, "IOException", ex); 
        req = findAndRemoveRequestFromList(rr.mSerial); 
        // make sure this request has not already been handled, 
        // eg, if RILReceiver cleared the list. 
        if (req != null || !alreadySubtracted) { 
         rr.onError(RADIO_NOT_AVAILABLE, null); 
         rr.release(); 
        } 
       } catch (RuntimeException exc) { 
        Rlog.e(LOG_TAG, "Uncaught exception ", exc); 
        req = findAndRemoveRequestFromList(rr.mSerial); 
        // make sure this request has not already been handled, 
        // eg, if RILReceiver cleared the list. 
        if (req != null || !alreadySubtracted) { 
         rr.onError(GENERIC_FAILURE, null); 
         rr.release(); 
        } 
       } finally { 
        // Note: We are "Done" only if there are no outstanding 
        // requests or replies. Thus this code path will only release 
        // the wake lock on errors. 
        releaseWakeLockIfDone(); 
       } 
       if (!alreadySubtracted && mRequestMessagesPending > 0) { 
        mRequestMessagesPending--; 
       } 
       break; 
      case EVENT_WAKE_LOCK_TIMEOUT: 
       // Haven't heard back from the last request. Assume we're 
       // not getting a response and release the wake lock. 
       synchronized (mWakeLock) { 
        if (mWakeLock.isHeld()) { 
         // The timer of WAKE_LOCK_TIMEOUT is reset with each 
         // new send request. So when WAKE_LOCK_TIMEOUT occurs 
         // all requests in mRequestList already waited at 
         // least DEFAULT_WAKE_LOCK_TIMEOUT but no response. 
         // Reset mRequestMessagesWaiting to enable 
         // releaseWakeLockIfDone(). 
         // 
         // Note: Keep mRequestList so that delayed response 
         // can still be handled when response finally comes. 
         if (mRequestMessagesWaiting != 0) { 
          Rlog.d(LOG_TAG, "NOTE: mReqWaiting is NOT 0 but" 
            + mRequestMessagesWaiting + " at TIMEOUT, reset!" 
            + " There still msg waitng for response"); 
          mRequestMessagesWaiting = 0; 
          if (RILJ_LOGD) { 
           synchronized (mRequestList) { 
            int count = mRequestList.size(); 
            Rlog.d(LOG_TAG, "WAKE_LOCK_TIMEOUT " + 
              " mRequestList=" + count); 
            for (int i = 0; i < count; i++) { 
             rr = mRequestList.get(i); 
             Rlog.d(LOG_TAG, i + ": [" + rr.mSerial + "] " 
               + requestToString(rr.mRequest)); 
            } 
           } 
          } 
         } 
         // mRequestMessagesPending shows how many 
         // requests are waiting to be sent (and before 
         // to be added in request list) since star the 
         // WAKE_LOCK_TIMEOUT timer. Since WAKE_LOCK_TIMEOUT 
         // is the expected time to get response, all requests 
         // should already sent out (i.e. 
         // mRequestMessagesPending is 0)while TIMEOUT occurs. 
         if (mRequestMessagesPending != 0) { 
          Rlog.e(LOG_TAG, "ERROR: mReqPending is NOT 0 but" 
            + mRequestMessagesPending + " at TIMEOUT, reset!"); 
          mRequestMessagesPending = 0; 
         } 
         mWakeLock.release(); 
        } 
       } 
       break; 
     } 
    } 
} 

class RILReceiver implements Runnable { 
    byte[] buffer; 
    RILReceiver() { 
     buffer = new byte[RIL_MAX_COMMAND_BYTES]; 
    } 
    public void 
    run() { 
     int retryCount = 0; 
     try {for (;;) { 
      LocalSocket s = null; 
      LocalSocketAddress l; 
      try { 
       s = new LocalSocket(); 
       l = new LocalSocketAddress(SOCKET_NAME_RIL, 
         LocalSocketAddress.Namespace.RESERVED); 
       s.connect(l); 
      } catch (IOException ex){ 
       try { 
        if (s != null) { 
         s.close(); 
        } 
       } catch (IOException ex2) { 
        //ignore failure to close after failure to connect 
       } 
       // don't print an error message after the the first time 
       // or after the 8th time 
       if (retryCount == 8) { 
        Rlog.e (LOG_TAG, 
         "Couldn't find '" + SOCKET_NAME_RIL 
         + "' socket after " + retryCount 
         + " times, continuing to retry silently"); 
       } else if (retryCount > 0 && retryCount < 8) { 
        Rlog.i (LOG_TAG, 
         "Couldn't find '" + SOCKET_NAME_RIL 
         + "' socket; retrying after timeout"); 
       } 
       try { 
        Thread.sleep(SOCKET_OPEN_RETRY_MILLIS); 
       } catch (InterruptedException er) { 
       } 
       retryCount++; 
       continue; 
      } 
      retryCount = 0; 
      mSocket = s; 
      Rlog.i(LOG_TAG, "Connected to '" + SOCKET_NAME_RIL + "' socket"); 
      int length = 0; 
      try { 
       InputStream is = mSocket.getInputStream(); 
       for (;;) { 
        Parcel p; 
        length = readRilMessage(is, buffer); 
        if (length < 0) { 
         // End-of-stream reached 
         break; 
        } 
        p = Parcel.obtain(); 
        p.unmarshall(buffer, 0, length); 
        p.setDataPosition(0); 
        //Rlog.v(LOG_TAG, "Read packet: " + length + " bytes"); 
        processResponse(p); 
        p.recycle(); 
       } 
      } catch (java.io.IOException ex) { 
       Rlog.i(LOG_TAG, "'" + SOCKET_NAME_RIL + "' socket closed", 
         ex); 
      } catch (Throwable tr) { 
       Rlog.e(LOG_TAG, "Uncaught exception read length=" + length + 
        "Exception:" + tr.toString()); 
      } 
      Rlog.i(LOG_TAG, "Disconnected from '" + SOCKET_NAME_RIL 
        + "' socket"); 
      setRadioState (RadioState.RADIO_UNAVAILABLE); 
      try { 
       mSocket.close(); 
      } catch (IOException ex) { 
      } 
      mSocket = null; 
      RILRequest.resetSerial(); 
      // Clear request list on close 
      clearRequestList(RADIO_NOT_AVAILABLE, false); 
     }} catch (Throwable tr) { 
      Rlog.e(LOG_TAG,"Uncaught exception", tr); 
     } 
     /* We're disconnected so we don't know the ril version */ 
     notifyRegistrantsRilConnectionChanged(-1); 
    } 
} 

Répondre

1

Donc, après avoir travaillé avec l'accrochage RIL pendant un moment, je peux répondre à la deuxième partie de votre message.

messages RIL peuvent être de deux types, et sollicité non sollicité.
Comment ceux-ci se traitées peut être vu dans la classe RIL java à partir des sources Android RIL.java

Mais je vais vous expliquer brièvement leur structure et la façon dont ils sont analysés:

SPONTANEES messages sont des messages qui RIL envoie en soi et sont généralement des événements liés à la radio. Un exemple d'un message non sollicité est:

1 0 0 0 -15 3 0 0 15 0 0 0 0 0 0 0 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 99 0 0 0 -1 -1 -1 127 -1 -1 -1 127 -1 -1 -1 127 -1 -1 -1 127 -1 -1 -1 127 

La structure est simple:

[type uint32 little endian][response uint32 little endian][data] 

si

1 0 0 0 = 1 is the type of the request, which means unsollicited message(notice the endianess) 
-15 3 0 0 = 1009 is the response , which matches RIL_UNSOL_SIGNAL_STRENGTH 
[15 0 . .]= data structure regarding signal strenght (in this case an array of strings) 

constantes de réponse peut être trouvée dans la classe RILConstants.java des sources.

SOLLICITÉ Les messages sont des réponses aux demandes envoyées par android à la couche RIL. Ceci est fait de façon asynchrone et android garde un wakelock en attente d'une réponse pour DEFAULT_WAKE_LOCK_TIMEOUT avant de relâcher le wakelock (même s'il est difficile de traiter la réponse quand il l'obtiendra finalement).
Les réponses SOLLICITED sont traitées un peu différemment, lors de l'envoi d'une requête android obtient une série globale pour la demande (as seen here), et l'enregistre dans une liste interne. Lorsqu'il reçoit une réponse, il trouve la réponse en utilisant le numéro de série (as seen here).
Un exemple d'un message sollicité est:

0 0 0 0 -94 0 0 0 17 0 0 0 

La structure est la suivante:

[type uint32 little endian][serial uint32 little endian][error uint32 little endian][data] 

si

0 0 0 0 = 0 is the type, UNSOLICITED 
-94 0 0 0 = 162 is the serial 
17 0 0 0 = 17 is the error (NO_SUCH_ELEMENT) 

Pour les constantes concernant l'erreur, vous devriez jeter un oeil à CommandException.java

Si vous voulez analyser les réponses SOLLICITED vous devez accrocher RILRequest.obtain pour être en mesure d'enregistrer une copie de valeur-clé de mSerial et mRequest pour pouvoir l'analyser (sinon vous ne pouvez pas connaître la demande)

Si vous voulez en savoir plus sur le couche entière RIL il y a une diapositive exaustive qui couvre à peu près tout android-radio-layer-interface.
En outre, plug sans vergogne, mais si vous voulez, vous pouvez jeter un oeil à un exemple de module que j'ai fait qui enregistre simplement les messages RIL. xposed-ril-wrapper