/*## (c) SECURITY EXPLORATIONS    2018 poland                                #*/
/*##     http://www.security-explorations.com                                #*/

/* THIS SOFTWARE IS PROTECTED BY DOMESTIC AND INTERNATIONAL COPYRIGHT LAWS    */
/* UNAUTHORISED COPYING OF THIS SOFTWARE IN EITHER SOURCE OR BINARY FORM IS   */
/* EXPRESSLY FORBIDDEN. ANY USE, INCLUDING THE REPRODUCTION, MODIFICATION,    */
/* DISTRIBUTION, TRANSMISSION, RE-PUBLICATION, STORAGE OR DISPLAY OF ANY      */
/* PART OF THE SOFTWARE, FOR COMMERCIAL OR ANY OTHER PURPOSES REQUIRES A      */
/* VALID LICENSE FROM THE COPYRIGHT HOLDER.                                   */

/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS    */
/* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,*/
/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL    */
/* SECURITY EXPLORATIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
/* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF  */
/* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE     */
/* SOFTWARE.                                                                  */

import java.lang.*;

public class EMMBlocker extends SCFilter {
 private static EMMBlocker emmblocker;

 private static boolean disable_req=false;
 private static boolean request_begin=false;

 public EMMBlocker() {
  super("EMM Blocker",ST_ALL);
 }

 public void process_emm_data(int buf,int size) {
  ApiMonitor.log("Blocked EMM data");

  byte tab[]=Utils.buf2barray(buf,size);
  ApiMonitor.log_buf(tab);
 }

 public boolean match(int prefix,int state,int cmd,int ptr,int buf,int size) {
  if (cmd==Conax.CMD_EMM) {
   if (prefix==SCInterface.IST_PRECALL) {
    switch(state) {
     case SCInterface.IST_WRITE_REQ_HDR:
     case SCInterface.IST_READ_REQ_CMD:
     case SCInterface.IST_WRITE_REQ_BODY:
     case SCInterface.IST_READ_RESP_CODE1:
     case SCInterface.IST_READ_RESP_CODE2:
      return true;
     default:
      return false;
    }
   } else {
    switch(state) {
     case SCInterface.IST_WRITE_REQ_HDR:
     case SCInterface.IST_WRITE_REQ_BODY:
      return true;
     default:
      return false;
    }
   }

  } else return false;
 }

 public boolean action(int prefix,int state,int cmd,int ptr,int buf,int size) {
  switch(prefix) {
   case SCInterface.IST_PRECALL:
    if (state==SCInterface.IST_WRITE_REQ_HDR) {
     if (disable_req) {
      emmblocker.disable();
      disable_req=false;
      request_begin=false;
      return true;
     }

     if (!request_begin) request_begin=true;
    } else

    if (state==SCInterface.IST_READ_REQ_CMD) {
     Memory.write_byte(buf,Conax.CMD_EMM);
     change_res(ptr,1);   
    } else

    if (state==SCInterface.IST_READ_RESP_CODE1) {
     Memory.write_byte(buf,Conax.CMD_RET_OK1);
     change_res(ptr,1);   
    } else

    if (state==SCInterface.IST_READ_RESP_CODE2) {
     Memory.write_byte(buf,Conax.CMD_RET_OK2);
     change_res(ptr,1);   
    }
    break;

   case SCInterface.IST_POSTCALL:
    if (state==SCInterface.IST_WRITE_REQ_HDR) {
     change_res(ptr,Conax.CMD_REQ_HDR_SIZE);
    } else

    if (state==SCInterface.IST_WRITE_REQ_BODY) {
     process_emm_data(buf,size);
     change_res(ptr,size);
    }
    break;
  }

  return !request_begin;
 }

 public static void start() {
  if (emmblocker==null) {
   emmblocker=new EMMBlocker();
   SCInterface.add_filter(emmblocker);
  }

  request_begin=false;
  emmblocker.enable();
 }

 public static void stop() {
  if (emmblocker!=null) {
   disable_req=true;
  }
 }

 public static boolean status() {
  if (emmblocker!=null) {
   return emmblocker.enabled();
  } else return false;
 }

}
