def system_check(self, runtime):
     """Check if /system is writable."""
     try:
         try:
             out = self.adb_command(['getprop', 'ro.build.version.sdk'],
                                    True)
             if out:
                 api = int(out.decode('utf-8').strip())
                 logger.info('Android API Level ' 'identified as %s', api)
                 if api > ANDROID_API_SUPPORTED:
                     logger.error('This API Level is not supported'
                                  ' for Dynamic Analysis.')
                     return False
         except Exception:
             pass
         err_msg = ('VM\'s /system is not writable. '
                    'This VM cannot be used for '
                    'Dynamic Analysis.')
         proc = subprocess.Popen([
             get_adb(), '-s', self.identifier, 'shell', 'touch',
             '/system/test'
         ],
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.PIPE)
         _, stderr = proc.communicate()
         if b'Read-only' in stderr:
             logger.error(err_msg)
             if runtime == 'emulator':
                 logger.error('Please start the AVD as per '
                              'Kensa documentation!')
             return False
     except Exception:
         logger.error(err_msg)
         return False
     return True
 def connect_n_mount(self):
     """Test ADB Connection."""
     self.adb_command(['kill-server'])
     self.adb_command(['start-server'])
     logger.info('ADB Restarted')
     self.wait(2)
     logger.info('Connecting to Android %s', self.identifier)
     if not self.run_subprocess_verify_output(
         [get_adb(), 'connect', self.identifier]):
         return False
     logger.info('Restarting ADB Daemon as root')
     if not self.run_subprocess_verify_output([get_adb(), 'root']):
         return False
     logger.info('Reconnecting to Android Device')
     # connect again with root adb
     if not self.run_subprocess_verify_output(
         [get_adb(), 'connect', self.identifier]):
         return False
     # identify environment
     runtime = self.get_environment()
     if runtime == 'emulator':
         logger.info('Found Android Studio Emulator')
         # mount system
         logger.info('Remounting')
         self.adb_command(['remount'])
     elif runtime == 'genymotion':
         logger.info('Found Genymotion x86 VM')
         # mount system
         logger.info('Remounting /system')
         self.adb_command(['mount', '-o', 'rw,remount', '/system'], True)
     else:
         logger.error('Only Genymotion VM/Android Studio Emulator'
                      ' is supported')
         return False
     logger.info('Performing System check')
     if not self.system_check(runtime):
         return False
     return True
    def adb_command(self, cmd_list, shell=False, silent=False):
        """ADB Command wrapper."""
        args = [get_adb(), '-s', self.identifier]
        if shell:
            args += ['shell']
        args += cmd_list

        try:
            result = subprocess.check_output(args)
            return result
        except Exception:
            if not silent:
                logger.exception('Error Running ADB Command')
            return None
 def is_kensayied(self, android_version):
     """Check is Device is Kensayed."""
     logger.info('Environment Kensayed Check')
     if android_version < 5:
         agent_file = '.kensa-x'
         agent_str = b'Kensa-Xposed'
     else:
         agent_file = '.kensa-f'
         agent_str = b'Kensa-Frida'
     try:
         out = subprocess.check_output([
             get_adb(), '-s', self.identifier, 'shell', 'cat',
             '/system/' + agent_file
         ])
         if agent_str not in out:
             return False
     except Exception:
         return False
     return True
def execute_adb(request):
    """Execute ADB Commands."""
    data = {'status': 'ok', 'message': ''}
    cmd = request.POST['cmd']
    if cmd:
        args = [get_adb(), '-s', get_device()]
        try:
            proc = subprocess.Popen(args + cmd.split(' '),
                                    stdout=subprocess.PIPE,
                                    stderr=subprocess.PIPE)
            stdout, stderr = proc.communicate()
        except Exception:
            logger.exception('Executing ADB Commands')
        if stdout or stderr:
            out = stdout or stderr
            out = out.decode('utf8', 'ignore')
        else:
            out = ''
        data = {'status': 'ok', 'message': out}
    return json_response(data)
 def enable_adb_reverse_tcp(self, version):
     """Enable ADB Reverse TCP for Proxy."""
     # Androd 5+ supported
     if not version >= 5:
         return
     proxy_port = settings.PROXY_PORT
     logger.info('Enabling ADB Reverse TCP on %s', proxy_port)
     tcp = 'tcp:{}'.format(proxy_port)
     try:
         proc = subprocess.Popen(
             [get_adb(), '-s', self.identifier, 'reverse', tcp, tcp],
             stdout=subprocess.PIPE,
             stderr=subprocess.PIPE)
         _, stderr = proc.communicate()
         if b'error: closed' in stderr:
             logger.warning('ADB Reverse TCP works only on'
                            ' Android 5.0 and above. Please '
                            'configure a reachable IP Address'
                            ' in Android proxy settings.')
         elif stderr:
             logger.error(stderr.decode('utf-8').replace('\n', ''))
     except Exception:
         logger.exception('Enabling ADB Reverse TCP')
 def start_frida():
     fnull = open(os.devnull, 'w')
     argz = [
         get_adb(), '-s', self.identifier, 'shell', '/system/fd_server'
     ]
     subprocess.call(argz, stdout=fnull, stderr=subprocess.STDOUT)