
{% extends "base/base_layout.html" %}
{% load static %}
{% block sidebar_option %}
    sidebar-collapse
{% endblock %}
{% block extra_css %}
<link rel="stylesheet" href="{% static "others/css/terminal.css" %}" type="text/css">
<link rel="stylesheet" href="{% static "others/css/devices.min.css" %}" type="text/css">
<link rel="stylesheet" href="{% static "codemirror/codemirror.css" %}" type="text/css">
<link rel="stylesheet" href="{% static "enlighterjs/enlighterjs.min.css" %}" />
<link rel="stylesheet" href="{% static "codemirror/lint.css" %}" type="text/css">
<link rel="stylesheet" href="{% static "others/css/spinner.css" %}">
<style>
     #stat {
        width: 100%;
        height: {% if android_version < 5 %} 630px; {% else %} 170px; {% endif %}
        -moz-border-bottom-colors: none;
        -moz-border-left-colors: none;
        -moz-border-right-colors: none;
        -moz-border-top-colors: none;
        background: none repeat scroll 0 0 rgba(0, 0, 0, 0.07);
        border-color: -moz-use-text-color #FFFFFF #FFFFFF -moz-use-text-color;
        border-image: none;
        border-radius: 6px 6px 6px 6px;
        border-style: none solid solid none;
        border-width: medium 1px 1px medium;
        box-shadow: 0 1px 2px rgba(0, 0, 0, 0.12) inset;
        color: #555555;
        font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
        font-size: 1em;
        line-height: 1.4em;
        padding: 5px 8px;
        transition: background-color 0.2s ease 0s;
    }
    #stat:focus {
        background: none repeat scroll 0 0 #FFFFFF;
        outline-width: 0;
    }
    .highlight { border: solid 2px #1e6dff;}
    
    #code-editor{
      transform: scale(1.25) !important;
      transform-origin: top left;
      width: 80%;
      height: auto;
      overflow: auto;
      max-height: 600px;
      border: 1px solid #ddd;
      border-radius: 4px;
      padding: 10px;
      background: #f8f9fa;
      margin-bottom: 150px;
      position: relative;
      z-index: 1;
      scrollbar-width: none; /* Firefox */
      -ms-overflow-style: none; /* Internet Explorer 10+ */
    }
    
    #code-editor::-webkit-scrollbar {
      display: none; /* Chrome, Safari, Opera */
    }
    .CodeMirror {
        height: 610px;
        font-size: 11px;
        border: 1px solid #eee;
      }

    .frida-pre {
      font-family: "courier new", courier, monospace;
      font-size: 11px;
    }

    #start_activity{
        margin-top: 5px;
    }
    #start_activity_form{
        margin-top: 10px;
    }

</style>

{% endblock %}

{% block content %}

<script src="{% static "adminlte/plugins/jquery.min.js" %}"></script>

<div class="content-wrapper">
  <div class="content-header">
    <div class="container-fluid">
      <div class="row mb-2">
        <div id="mobsf_header" align="center" style="padding-left: 20px;">
            <h2><strong>Dynamic Analyzer </strong>- {{ package }}</h2>
        </div>
      </div>
    </div>
  </div>
   <div class="container-fluid">

   
   <div class="row">
          <div class="col-md-12">
            <div class="card card-default">
              <!-- /.card-header -->
              <div class="card-body">
                 <div id="but" align="center">
                  <a href="#" id="screen" class="btn btn-primary" role="button"><i class="fa fa-mobile-alt"></i> Show Screen</a>
                  <a href="#" id="rootca" class="btn btn-primary" role="button"><i class="fa fa-certificate"></i> Remove Root CA</a>
                  {% if android_version >= 5 %}
                  <a href="#" id="proxy" class="btn btn-primary" role="button"><i class="fas fa-eye-slash"></i> Unset HTTP(S) Proxy</a>
                  <a href="#" id="tls_test" class="btn btn-primary" role="button"  data-toggle="modal" data-target="#tls_modal"><i class="fa fa-lock"></i> TLS/SSL Security Tester</a>
                  {% endif %}
                  <a href="#" id="expactt" class="btn btn-primary" role="button"><i class="fa fa-language"></i> Exported Activity Tester</a>
                  <a href="#" id="actt" class="btn btn-primary" role="button"><i class="fa fa-rocket"></i> Activity Tester</a>
                  {% if android_version >= 5 %}
                  <a href="#" id="deps" class="btn btn-primary" role="button"><i class="fas fa-running"></i> Get Dependencies</a>
                  {% endif %}
                  <a href="#" id="ss" class="btn btn-primary" role="button"><i class="fa fa-camera"></i> Take a Screenshot</a>
                  <a href="#" id="logstream" class="btn btn-primary"><i class="fa fa-water"></i> Logcat Stream</a>
                  <a href="{% url 'live_api' %}?hash={{ hash }}&amp;package={{ package }}" id="apimon" target="_blank" class="btn btn-primary" style='display: none'><i class="fa fa-search"></i> Live API Monitor</a>
                  <a href="#" id="stop" class="btn btn-info" role="button" ><i class="fa fa-file-alt"></i> Generate Report</a>
                </div>
              </div>
              <!-- /.card-body -->
            </div>
            <!-- /.card -->
          </div>
          <!-- /.col -->


          <div class="col-md-3">
            <div class="card card-default">
              <!-- /.card-header -->
              <div class="card-body">
                <div align="center">
                  <div class="marvel-device htc-one">
                  <div class="top-bar"></div>
                  <div class="camera"></div>
                  <div class="sensor"></div>
                  <div class="speaker"></div>
                  <div class="screen" id="container" tabindex="0" style="outline: none;">
                  <img width="320" height="580" src="{% url 'download' %}screen/screen.png" id="my" onerror="$('#my').attr('src','/static/img/loading.jpg')" style="background-color:black;">
                  </div>
                  </div>
                </div>

                <div class="card-body">
                  <p>
                  <div class="input-group input-group-sm">
                    <input class="form-control form-control-navbar" id="android_text" type="text" placeholder="Text Input" >
                    <div class="input-group-append">
                      <button id="android_text_btn" class="btn btn-primary">
                        <i class="far fa-paper-plane"></i>
                      </button>
                    </div>
                  </div>
                </p>
              </div>

              </div>
              <!-- /.card-body -->
            </div>
            <!-- /.card -->
          </div>
          <!-- /.col -->

           <div class="col-md-{% if android_version < 5 %}9{% else %}4{% endif %}">
            <div class="card card-default">
              <!-- /.card-header -->
              <div class="card-body">

            <div class="card card-primary card-outline card-outline-tabs">
              <div class="card-header p-0 border-bottom-0">
                <ul class="nav nav-tabs" id="tabnav" role="tablist">
                  <li class="nav-item">
                    <a class="nav-link active" id="dm-tab" data-toggle="pill" href="#dm" role="tab" aria-controls="dm" aria-selected="true">Dynamic Analyzer</a>
                  </li>
                  <li class="nav-item">
                    <a class="nav-link" id="errors-tab" data-toggle="pill" href="#errors" role="tab" aria-controls="errors" aria-selected="false">Errors</a>
                  </li>
                </ul>
              </div>
              <div class="card-body">
                <div class="tab-content" id="tabs">
                  <div class="tab-pane fade active show" id="dm" role="tabpanel" aria-labelledby="dm-tab">
                  <textarea id="stat"></textarea>
                {% if android_version < 5 %}
                <!-- xposed only-->
                <br>
                <button id="run_app" class="btn btn-success"><i class="fas fa-play"></i> Run App</button>
                {% endif %}
                <!--box-->
                <div class="box box-primary">
                    <!-- /.box-header -->
                    <!-- form start -->
                    <form role="form">
                      <div class="box-body">
                      <div id="frida_options">
                        <hr/>
                          <div class="form-group">
                          <h4> Default Frida Scripts </h4>
                            <label>
                                <input name="default_hooks" type="checkbox" value="api_monitor" checked>
                                API Monitoring 
                              </label>
                              <label>
                                <input name="default_hooks" type="checkbox" value="ssl_pinning_bypass" checked>
                                SSL Pinning Bypass 
                              </label>
                              <label>
                              <input name="default_hooks" type="checkbox"  value="root_bypass" checked>
                                Root Detection Bypass 
                              </label>
                              <label>
                              <input name="default_hooks" type="checkbox" value="debugger_check_bypass" checked>
                                Debugger Check Bypass
                              </label>
                              <label>
                                <input name="default_hooks" type="checkbox" value="dump_clipboard" checked>
                                Clipboard Monitor
                                </label>
                          </div>
                        <hr/>
                       <div class="form-group">
                        <h4> Auxiliary Frida Scripts</h4>
                            <label>
                            <input name="auxiliary" type="checkbox" value="enum_class" id="enum_class">
                              Enumerate Loaded Classes
                            </label> 
                             <label>
                            <input name="auxiliary" type="checkbox" value="string_catch" id="string_catch">
                               Capture Strings
                            </label>
                             <label>
                            <input name="auxiliary" type="checkbox" value="string_compare" id="string_compare">
                                Capture String Comparisons
                            </label>
                            <br />
                             <label>
                              <input onclick="aux_click(this)" name="auxiliary" type="checkbox" value="enum_methods" id="enum_methods">
                              Enumerate Class methods
                            </label>
                             <input type="text" class="form-control" id="class_name" placeholder="java.io.File">

                             <label>
                              <input onclick="aux_click(this)" name="auxiliary" type="checkbox" value="search_class" id="search_class">
                              Search Class Pattern
                            </label>
                             <input type="text" class="form-control" id="class_search" placeholder="ssl\.Trust*">
                             <label>
                             <input onclick="aux_click(this)" name="auxiliary" type="checkbox"  value="trace_class" id="trace_class">
                              Trace Class Methods
                            </label>
                             <input type="text" class="form-control" id="class_trace" placeholder="java.net.Socket,java.io.File,java.lang.String">
                       </div>
                    
                        <hr/>
                        <div class="form-group">
                          <h4> Instrumentation </h4>
                        </div>

                        <div class="box-footer">
                          <button id="frida_spawn" type="submit" class="btn btn-success btn-sm"><i class="far fa-play-circle"></i> Spawn & Inject</button>
                          <button id="frida_session" type="submit" class="btn btn-success btn-sm" disabled><i class="fas fa-redo"></i> Inject </button>
                          <button id="frida_attach" type="submit" class="btn btn-success btn-sm"><i class="fas fa-bug"></i> Attach </button>
                          <button id="frida_get" class="btn btn-primary btn-sm" hidden><i class="fas fa-code"></i> Injected Code</button>
                       </div>
                      </div>  <!--Frida options, hidden for xposed -->


                        <hr/>
                        <div class="form-group">
                          <h4> User Interface </h4>
                        </div>

                        {% if activities or exported_activities %}
                        <label class="box-title" for="activities">Activities</label>
                        <div class="form-group form-inline" id="start_activity_form">
                          <select style="width: 15rem" class="form-select form-control form-group mb-2 mr-3" name="activities" id="activities">
                            <optgroup label="Exported Activities">
                              {% for activity in exported_activities %}
                            <option value="{{ activity }}">{{ activity }}</option>
                                      {% endfor %}
                            </optgroup>
                            <optgroup label="Activities">
                                        {% for activity in activities %}
                              <option value="{{ activity }}">{{ activity }}</option>
                                        {% endfor %}
                            </optgroup>
                          </select>
                          <button id="start_activity" type="submit" class="btn btn-primary btn-sm form-group mb-2">♢ Start Activity</button>
                        </div>
                        {% endif %}
            
                        {% if deeplinks %}
                        <div class="mt-3">
                          <label class="box-title" for="deeplinks">Deep Links</label>
                          <div class="form-group form-inline">
                            <select class="form-select form-control form-group mb-2 mr-2" name="schemes" id="schemes">
                            {% for activity, intent in deeplinks.items %}
                              <optgroup label="{{ activity }} - Schemes">
                                {% for scheme in intent.schemes %}
                                  <option value="{{ scheme }}">{{ scheme }}</option>
                                {% endfor %}
                              </optgroup>
                            {% endfor %}
                            </select>
                            <select class="form-select form-control form-group mb-2 mr-2" name="hosts" id="hosts">
                              {% for activity, intent in deeplinks.items %}
                                <optgroup label="{{ activity }} - Hosts">
                                  {% for host in intent.hosts %}
                                    <option value="{{ host }}">{{ host }}</option>
                                  {% endfor %}
                                  <option value=""></option>
                                </optgroup>
                              {% endfor %}
                            </select>
                            <select class="form-select form-control form-group mb-2 mr-2" name="paths" id="paths">
                              {% for activity, intent in deeplinks.items %}
                                <optgroup label="{{ activity }} - Paths/PathPrefixes">
                                  {% for path in intent.paths %}
                                    <option value="{{ path }}">{{ path }}</option>
                                  {% endfor %}
                                  {% for path_prefix in intent.path_prefixs %}
                                    <option value="{{ path_prefix }}">{{ path_prefix }}</option>
                                  {% endfor %}
                                  <option value=""></option>
                                </optgroup>
                              {% endfor %}
                            </select>
                            <input type="text" class="form-control form-group mb-2 mr-2" id="query" placeholder="/foo?bar=">
                            <button id="start_deeplink" type="submit" class="btn btn-primary btn-sm form-group mb-2">▶ Deeplink</button>
                          </div>
                        </div>
                        {% endif %}
                        
                      </div>
                      <!-- /.box-body -->
                     
                    </form>
                  </div>
           
                 

               

                  
              <!--tab end-->

                  </div>

                  <div class="tab-pane fade" id="errors" role="tabpanel" aria-labelledby="errors-tab">
                    <iframe sandbox frameborder="0" width="100%" height="650px" id="er"></iframe>
                  </div>
                </div>
              </div>
              <!-- /.card -->
            </div>


              </div>
              <!-- /.card-body -->
            </div>
            <!-- /.card -->
          </div>
          <!-- /.col -->

           <div class="col-md-5" id="codeedit">
            <div class="card card-default">
              <div class="card-header">
                <h3 class="card-title"><i class="fa fa-code"></i> Frida Code Editor </h3>
                <!-- /.card-tools -->
              </div>
              <!-- /.card-header -->
              <div class="card-body">
                <div id="code-editor">
<textarea id="code-js" rows="100">
  Java.perform(function() {
    // Use send() for logging
  });
</textarea>
                </div>
                <br/>
                <div class="form-group">
                  <span class="box-title">Available Scripts (Use CTRL to choose multiple)  </span>
                  <button id="loadscript" type="submit" class="btn btn-primary btn-sm">Load</button>
                </div>
                <div class="form-group">
                  <select id="fd_scs" size="10" multiple="" class="form-control">
                  </select>
                </div>
              
              </div>
              <!-- /.card-body -->
            </div>
            <!-- /.card -->
          </div>
          <!-- /.col -->

            <div class="col-md-12">
            <div class="card card-default">
              <!-- /.card-header -->
              <div class="card-body">
                   
                   <div id="shell">
                    <output></output>
                    <div id="input-line" class="input-line">
                      <div class="prompt"></div><div><input class="cmdline" autofocus /></div>
                    </div>
                  </div>
              
              </div>
              <!-- /.card-body -->
            </div>
            <!-- /.card -->
          </div>
          <!-- /.col -->


          <div class="col-md-12">
            <div class="card card-default">
              <!-- /.card-header -->
              <div class="card-body">
                   <div>
                    <h4 class="page-header"><strong>Frida Logs </strong></h4>
                    <div id="messages"></br>Data refreshed in every 3 seconds.</div>
                    <pre class="frida-pre" id="frida-logs" style="font-size:15pt"></pre>
                  </div>
              </div>
              <!-- /.card-body -->
            </div>
            <!-- /.card -->
          </div>
          <!-- /.col -->

        
        </div>

        </div>
       </div>
     </div>
    </div>
</div>

<!--Loader-->
<div class="hidden loading">
  <div class='uil-ring-css' style='transform:scale(0.79);'>
    <div></div>
  </div>
  </div>
<!-- Modal -->
<div class="modal fade" id="frida_attach_mdl" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
  <div class="modal-dialog" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title" id="exampleModalLabel">Attach to a Running Process</h5>
        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body">
        <form role="form">
          <div class="form-group">
            <select id="process_select" class="form-select" aria-label="Select a process">
            </select>
          </div>
        </form>
      </div>
      <div class="modal-footer">
        <button id="attach_to_pid" type="button" class="btn btn-primary"><i class="fas fa-bug"></i> Attach</button>
      </div>

    </div>
  </div>
</div>

 <!-- Modal -->
 <div class="modal fade" id="get_code_modal" tabindex="-1" role="dialog">
  <div class="modal-dialog modal-xl">
    <div class="modal-content">
      <div class="modal-header">
        <h4 class="modal-title">Injected Frida Script</h4>
        <button type="button" class="close" data-dismiss="modal">&times;</button>
      </div>
      <div class="modal-body" id="injected_content">
      </div>
    </div>
  </div>
</div>


<!-- Modal -->
<div class="modal" id="tls_modal" tabindex="-1" role="dialog">
  <div class="modal-dialog modal-xl">
    <div class="modal-content">
      <div class="modal-header">
        <h4 class="modal-title">Run TLS/SSL Security Tests - {{ package }}</h4>
        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">×</span>
        </button>
      </div>
      <div class="modal-body">
        <form role="form">
            <div class="form-group">
                <p>TLS/SSL Security test helps you to evaluate the security of your application's network connections. These tests are applicable only for applications that performs network connections over HTTP protocol. We run multiple TLS/SSL tests against the application.<br>
                </p>
                <p>
                <strong>TLS Misconfiguration Test </strong> - Enable HTTPS MITM Proxy, Remove Root CA, Run the App for 25 seconds.<br>
                <code>This test will uncover insecure configurations that allow HTTPS connections bypassing certificate errors or SSL/TLS errors in WebViews. This is equivalent to not having TLS.</code><br>
                </p>
                <p>
                <strong>TLS Pinning/Certificate Transparency Test </strong> - Enable HTTPS MITM Proxy, Install Root CA, Run the App for 25 seconds.<br>
                <code>This test will evaluate the application's TLS/SSL hardening controls and will check if the application implement certificate or public key pinning and or certificate transparency.</code><br>
                <p>
                <strong>TLS Pinning/Certificate Transparency Bypass Test </strong> - Enable HTTPS MITM Proxy, Install Root CA, Bypass Certificate/Public Key Pinning or Certificate Transparency.<br>
                <code>This test tries to bypass certificate or public key pinning and or certificate transparency controls in your application. MobSF can bypass most of the generic implementations.</code><br>
                </p>
                <p><strong>NOTE: </strong><i>For Better results, while the application is running, navigate through different business logic flows that will trigger network connections over HTTP protocol. Make sure that no other applications are running during the test.</i></p>
              </div>
            <div class="form-group">
              <label>Test Progress</label>
              <textarea id="tls_text" class="form-control" rows="10" placeholder="" disabled=""></textarea>
            </div>
            <div class="form-group">
              <table class="table table-bordered table-hover table-striped">
                <thead>
                    <tr>
                      <th>TESTS</th>
                      <th>RESULT</th>
                  </tr>
                </thead>
                <tbody>
                   <tr>
                    <td>TLS Misconfiguration Test</td>
                    <td id="tls_1">-</td>
                  </tr>
                  <tr>
                    <td>TLS Pinning/Certificate Transparency Test</td>
                    <td id="tls_2">-</td>
                  </tr>
                  <tr>
                    <td>TLS Pinning/Certificate Transparency Bypass Test</td>
                    <td id="tls_3">-</td>
                  </tr>
                  <tr>
                    <td>Cleartext Traffic Test</td>
                    <td id="tls_4">-</td>
                  </tr>
              </tbody>
              </table>
            </div>

          </form>
      </div>
       <div class="modal-footer">
        <button id="run_tls_tests" type="button" class="btn btn-primary"><i class="fas fa-bolt"></i> Run TLS/SSL Tests</button>
      </div>
    </div>



    <!-- /.modal-content -->
  </div>
  <!-- /.modal-dialog -->
</div>
<!-- End Modal -->

{% endblock %}
{% block extra_scripts %}
<script src="{% static "codemirror/codemirror.js" %}"></script>
<script src="{% static "codemirror/javascript.js" %}"></script>
<script src="{% static "codemirror/jshint.js" %}"></script>
<script src="{% static "codemirror/lint.js" %}"></script>
<script src="{% static "codemirror/javascript-lint.js" %}"></script>
<script src="{% static "others/js/swipe.js" %}"></script>
<script src="{% static "enlighterjs/enlighterjs.min.js" %}"></script>
<script>
// Loading Spinner
function dynamic_loader(){
    var loadingOverlay = document.querySelector('.loading');
    loadingOverlay.classList.remove('hidden');
}
function stop_loader(){
    var loadingOverlay = document.querySelector('.loading');
    loadingOverlay.classList.add('hidden');
}

// Prevent screen image drag
document.getElementById('my').ondragstart = function() { return false; };

// Hide Frida Logs on page load
document.getElementById('frida-logs').style.display = 'none';

// Frida Auxiliary actions

function aux_click(cb) {
  if (cb.checked && cb.value==='search_class')
    $('#cls_search').addClass('highlight')
  else if (!cb.checked && cb.value==='search_class')
    $('#cls_search').removeClass('highlight')
  else if (cb.checked && cb.value==='enum_methods')
    $('#cls_name').addClass('highlight')
  else if (!cb.checked && cb.value==='enum_methods')
    $('#cls_name').removeClass('highlight')
  else if (cb.checked && cb.value==='trace_class')
    $('#cls_trace').addClass('highlight')
  else if (!cb.checked && cb.value==='trace_class')
    $('#cls_trace').removeClass('highlight')
}



//For All Ajax
function action(url, data, on_success){
  //Add CSRF
  data.csrfmiddlewaretoken ='{{ csrf_token }}';
  $.ajax({
    url : url, 
    type : "POST",
    dataType: "json", 
    data : data,
    success : function(json){ on_success(json) },
    error : function(xhr, ajaxOptions, thrownError) {
      document.getElementById("er").srcdoc = xhr.responseText;
    }
  });
}

// Escape
function escape(data_string) {
    var encodedStr = data_string.replace(/[\u00A0-\u9999<>\&]/gim, function (i) {
        return '&#' + i.charCodeAt(0) + ';';
    });
    return encodedStr;
}

// Escape HTML
function escapeHtml(unsafe){
    return unsafe
        .replace(/&/g, "&amp;")
        .replace(/</g, "&lt;")
        .replace(/>/g, "&gt;")
        .replace(/"/g, "&quot;")
        .replace(/'/g, "&#039;");
}

// Frida load other scripts
function load_frida_others(){
  action('{% url 'list_frida_scripts' %}', {device: 'android'}, function(json) {
    if (json.status==="ok"){
        json.files.forEach(function(script) {
          $('<option>').val(script).text(script).appendTo('#fd_scs');
        });
    }
  });
}

// Code Editor
var editor = CodeMirror.fromTextArea(document.getElementById("code-js"), {
    lineNumbers: true,
    mode: "javascript",
    gutters: ["CodeMirror-lint-markers"],
    lint: true,
    lineWrapping: true
  });

// Restore saved content
restore();

//Restore Code
function restore(){
  var custom_code = window.sessionStorage.getItem("code_android");
  if (custom_code !== null) {
    setTimeout(function(){ editor.getDoc().setValue(custom_code); }, 2000);
  }
}

// Terminal
var util = util || {};
util.toArray = function (list) {
    return Array.prototype.slice.call(list || [], 0);
};

var Terminal = Terminal || function (cmdLineContainer, outputContainer) {
    window.URL = window.URL || window.webkitURL;
    window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;

    var cmdLine_ = document.querySelector(cmdLineContainer);
    var output_ = document.querySelector(outputContainer);

    const CMDS_ = [
        'activities', 'exported_activities', 'services', 'receivers', 'providers', 'libraries',
        'clear', 'date', 'echo', 'help', 'shell', 'pull', 'push',
        'devices', 'forward', 'start-server', 'kill-server', 'wait-for-device',
        'connect', 'reconnect', 'disconnect', 'usb', 'install', 'uninstall',
        'logcat', 'root', 'sideload', 'tcpip', 'unroot',
        'reboot', 'remount', 'get-devpath', 'get-serialno', 'get-state',
        'keygen', 'enable-verity', 'disable-verity', 'jdwp', 'bugreport',
        'backup', 'restore', 'install-multi-package', 'install-multiple',
        'sync', 'reverse', 'ppp', 'version',

    ];

    var history_ = [];
    var histpos_ = 0;
    var histtemp_ = 0;
    var intro = '<h3 style="letter-spacing: 2px">Shell Access</h3><p>' + new Date() + '</p><p>Enter "help" for more information.</p>';
    var shell = document.getElementById('shell');
    shell.addEventListener('click', function (e) {
        cmdLine_.focus();
    }, false);

    cmdLine_.addEventListener('click', inputTextClick_, false);
    cmdLine_.addEventListener('keydown', historyHandler_, false);
    cmdLine_.addEventListener('keydown', processNewCommand_, false);

    function inputTextClick_(e) {
        this.value = this.value;
    }

    function historyHandler_(e) {
        if (history_.length) {
            if (e.keyCode == 38 || e.keyCode == 40) {
                if (history_[histpos_]) {
                    history_[histpos_] = this.value;
                } else {
                    histtemp_ = this.value;
                }
            }

            if (e.keyCode == 38) { // up
                histpos_--;
                if (histpos_ < 0) {
                    histpos_ = 0;
                }
            } else if (e.keyCode == 40) { // down
                histpos_++;
                if (histpos_ > history_.length) {
                    histpos_ = history_.length;
                }
            }

            if (e.keyCode == 38 || e.keyCode == 40) {
                this.value = history_[histpos_] ? history_[histpos_] : histtemp_;
                setTimeout(() => {
                    this.setSelectionRange(this.value.length, this.value.length);
                }, 0); // Sets cursor to end of input.
            }
        }
    }


    function output(html, escape_=false, pre=false, error=false) {
        if (escape_)
            html = escape(html);
        if (pre)
         output_.insertAdjacentHTML('beforeEnd', '<pre class="clean-text">' + html + '</pre>');
        else if (error)
          output_.insertAdjacentHTML('beforeEnd', '<pre>' + html + '</pre>');
        else
         output_.insertAdjacentHTML('beforeEnd', '<p>' + html + '</p>');
    }

    function scrollToShellBottom(){
      // Scroll to shell bottom and ensure shell is completely visible
      var myElement = document.getElementById('shell');
      
      // Scroll the shell content to the bottom
      myElement.scrollTop = myElement.scrollHeight;
      
      // Ensure the shell element is visible in the viewport
      myElement.scrollIntoView({ 
        block: 'end', 
        behavior: 'smooth',
        inline: 'nearest'
      });
      
      // For dynamic content, we need to continuously monitor and scroll
      // Set up a MutationObserver to watch for content changes
      if (!window.shellObserver) {
        window.shellObserver = new MutationObserver(function(mutations) {
          // When content changes, scroll to keep shell visible
          myElement.scrollTop = myElement.scrollHeight;
          myElement.scrollIntoView({ 
            block: 'end', 
            behavior: 'smooth',
            inline: 'nearest'
          });
        });
        
        // Start observing the shell for content changes
        window.shellObserver.observe(myElement, {
          childList: true,
          subtree: true,
          characterData: true
        });
      }
    }


    function get_comp(comp){
      action(document.location.origin + '/get_component/', { component: comp, hash: '{{ hash }}'}, function(json) {
          if (json.status==="ok")
            output(json.message, true, true);
          else
            output(json.message, true, true, true);
      });
    }

    function execute_adb(exec_cmd){
      action(document.location.origin + '/execute_adb/', { cmd: exec_cmd }, function(json) {
          if (json.status==="ok")
            output(json.message, true, true);
      });
    }
    function processNewCommand_(e) {

        if (e.keyCode == 9) { // tab
            e.preventDefault();
            // Implement tab suggest.
        } else if (e.keyCode == 13) { // enter
            // Save shell history.
            if (this.value) {
                history_[history_.length] = this.value;
                histpos_ = history_.length;
            }

            // Duplicate current input and append to output section.
            var line = this.parentNode.parentNode.cloneNode(true);
            line.removeAttribute('id')
            line.classList.add('line');
            var input = line.querySelector('input.cmdline');
            input.autofocus = false;
            input.readOnly = true;
            output_.appendChild(line);

            if (this.value && this.value.trim()) {
                var args = this.value.split(' ').filter(function (val, i) {
                    return val;
                });
                var cmd = args[0].toLowerCase();
                var exec_cmd = args.join(' ');
                args = args.splice(1); // Remove cmd from arg list.
            }

            switch (cmd) {
                case 'clear':
                    output_.innerHTML = '';
                    this.value = '';
                    output(intro);
                    return;
                case 'date':
                    output(new Date());
                    break;
                case 'echo':
                    output(exec_cmd, true);
                    break;
                case 'activities':
                    get_comp('activities')
                    break;
                case 'exported_activities':
                    get_comp('exported_activities')
                    break;
                case 'services':
                    get_comp('services')
                    break;
                case 'receivers':
                    get_comp('receivers')
                    break;
                case 'providers':
                    get_comp('providers')
                    break;
                case 'libraries':
                    get_comp('libraries')
                    break;
                case 'help':
                    output('<div class="ls-files">' + CMDS_.join('<br>') + '</div>');
                    break;                      
                default:
                    if (cmd === 'shell' && args.length === 0)
                        output("Incomplete command. expecting shell &lt;cmd&gt;");
                    else if (exec_cmd.length > 0)
                        execute_adb(exec_cmd)
            };
            scrollToShellBottom();
            this.value = ''; // Clear/setup line for next input.
        }
    }
    return {
        init: function () {
            output(intro);
        },
        output: output
    }
};

$(document).ready(function() {

//Terminal
$('.prompt').html('[root@android] # ');
var term = new Terminal('#input-line .cmdline', '#shell output');
term.init();


//Start Specific Activity
$("#start_activity").click(function(){
  let activity = $('#activities option:selected').val();
  print_status("Starting Activity: " + activity)
  start_activity(activity)
  return false;
});

// Start deeplink
$("#start_deeplink").click(function(){
  let scheme = $('#schemes option:selected').val();
  let host = $('#hosts option:selected').val();
  let path = $('#paths option:selected').val();
  let query = $('#query').val();

  if (scheme === undefined && host === undefined){
    print_status("Please select a valid scheme and host.")
    return false;
  }
  if (path === undefined)
    path = '';
  let url = scheme + host + path + query;
  print_status("Triggering Deeplink: " + url);
  start_deeplink(url)
  return false;
});


// Start up
{% if android_version < 5 %}
  $('#frida_options').hide()
  $('#codeedit').hide()
{% else %}
   load_frida_others();
{% endif %}


// Disable Activity Tester and Exported Activity Tester for on Device only apps
var loc = location.href;
if (loc.includes('&install=0')){
    $('#expactt').hide();
    $('#actt').hide();
}



//Print Status
function print_status(message){
  $('#stat').append(message + '\n');
  $('#stat').scrollTop($('#stat')[0].scrollHeight);
}
//Print TLS/SSL test progress inside modal
function print_tls_progress(message){
  $('#tls_text').append(message + '\n');
  $('#tls_text').scrollTop($('#tls_text')[0].scrollHeight);
}

print_status("Setting up MobSF Dynamic Analysis environment...");
print_status("Running HTTP(S) interception proxy.");
print_status("Invoking MobSF agents.");
print_status("Environment is ready for Dynamic Analysis.");
print_status("Start Instrumentation or Run the application and navigate through the different flows or business logic manually.");

// Frida Logs

function get_logs(){
      $.ajax({
        url : '{% url 'frida_logs' %}?hash={{ hash }}&stream=1', 
        type : "GET",
        dataType: "json", 
        success : function(json){ 
          if (json.status==="ok"){
            $('#frida-logs').text(json.message);
          } else {
            $('#frida-logs').text('')
          }
        },
        error : function(xhr, ajaxOptions, thrownError) {
          console.log(xhr.responseText);
        }
      });
}
get_logs();
setInterval( function () {
      get_logs();
}, 3000 );

// View Screen
var screen_width, screen_height;
var screenfunc;
$("#screen").click(function() {
      var stext = $("#screen").text();
      if (stext.includes("Show Screen")){
          $("#screen").html("<i class='fa fa-mobile'></i> Stop Screen");
          print_status('Screen streaming started.')
          touch = "on";
          screenfunc = setInterval(function(){
              // Capture Screen
              action('{% url 'screen_cast' %}', {}, function(json) {
                if (json.status == 'ok'){
                  if (screen_width === undefined || screen_height === undefined){
                    // Get Screen Resolution from Image
                    var i = new Image();
                    i.onload = function(){
                      screen_width = i.width;
                      screen_height = i.height;
                      console.log('Screen Resolution: ' + screen_width + 'x' + screen_height)
                      i = null;
                    };
                    i.src = json.message;
                  }
                  $('#my').attr('src', json.message);
                } else
                  console.log(json.message)
               });
          }, 2000);
      } else {
          $("#screen").html("<i class='fa fa-mobile-alt'></i> Show Screen");
          print_status("Screen streaming stopped.");
          $('#my').attr('src', '/static/img/loading.jpg');
          clearInterval(screenfunc);
          touch = "off";
      }
      return false;  
}); 


// Touch Events
var touch = "off";
function android_input(event, x, y){
  if ( touch === "on"){
    action('{% url 'android_touch' %}', { event, x, y, max_x: screen_width, max_y:screen_height}, function(json) {
        if (json.status==='ok')
          console.log('Event: ' + event);
        else
          console.log(json.message)
    });
  }
}

var xaxis, yaxis = 0;

function getXY(e, t){
      // X-Y axis for clicks
      var offset = $(t).offset();
      var x = e.pageX - offset.left;
      var y = e.pageY - offset.top;
      xaxis = x * (screen_width/320); 
      yaxis = y * (screen_height/580);
      console.log('X Axis: '+ xaxis + " Y Axis: "+ yaxis);
}

// Touch Screen Click Events
var pressedTime;
var releaseTime;
$("#my").on( "mousedown", function() {
  pressedTime = new Date().getTime();
});

$("#my").on( "mouseup", function(e) {
  releaseTime = new Date().getTime();
  getXY(e, this);
  if (releaseTime - pressedTime < 300 && touch === "on") {
          android_input('touch', xaxis, yaxis);
      }
});


// Touch Text Input
$('#android_text_btn').click(function(e) {
  if ($('#android_text').val()){
    // Send the text to device
    android_input('text', $('#android_text').val(), 0);
    $('#android_text').val('');
  } else {
    // send the enter event
    android_input('enter', 0, 0);
  }
});

// Keyboard Events
$('#container').on('keypress', function(event) {
    // Detect printable characters
    if (touch === "on"){
        switch(event.keyCode){
          case 13:
            // Enter
            // Send text to VM
            $('#android_text_btn').click();
            break;
          case 32:
            // Space
            // Prevent space propagation to page scroll
            $('#android_text').val($('#android_text').val() + ' ');
            event.preventDefault();
            break;
          default:
          $('#android_text').val($('#android_text').val() + String.fromCharCode(event.keyCode));
        }
    }
 });
 $('#container').on('keydown', function(event) {
    // Detect Backspace etc.
    if (touch === "on")
    {
        switch(event.keyCode){
          case 8:
            // Backspace
            android_input('backspace', 0, 0)
            break;
          case 37:
            // Left
            android_input('left', 0, 0)
            break;
          case 39:
            // Left
            android_input('right', 0, 0)
            break;
        }
    }
 });
 // Send text on enter from text box
 $('#android_text').keypress(function(event){
  if (touch === "on"){
    var keycode = (event.keyCode ? event.keyCode : event.which);
    if(keycode === 13){
      $('#android_text_btn').click();
    }
	event.stopPropagation();
  }
});


// Touch Swipe Events
const box = document.getElementById("my");
const classes = Swipe.directions();
const swipe = new Swipe(box, {
  corners: true,
  minDistance: 100
});

swipe.addEventListener("after", direction => {
  if (touch === "on") {
    switch(direction){
      case 'up': case 'leftup': case 'rightup':
        android_input('swipe_down', xaxis, yaxis)
        break;
      case 'down': case 'leftdown': case 'rightdown':
        android_input('swipe_up', xaxis, yaxis)
        break;
      case 'left':
        android_input('swipe_right', xaxis, yaxis)
        break;
      case 'right':
        android_input('swipe_left', xaxis, yaxis)
        break;
    }
}
});


//Screenshot
$("#ss").click(function() {
  print_status("Taking a screenshot.");
  action(document.location.origin + '/screenshot/', {hash: '{{ hash }}'}, function(json) {
    if (json.status==="ok"){
        print_status("Screenshot taken!");
    } else {
        print_status("Failed to take screenshot!");
        print_status(json.message);
    }
  });
  return false;  
});

//MobSF CA

$("#rootca").click(function() {
  var stext = $("#rootca").text();
  var act;
  if (stext.includes("Remove Root CA")){
    $("#rootca").html("<i class='fa fa-certificate'></i> Install Root CA");
    act = "remove";
  } else {
    $("#rootca").html("<i class='fa fa-certificate'></i> Remove Root CA");
    act = "install";
  }
  action(document.location.origin + '/mobsf_ca/', {action: act}, function(json) {
      if (json.message === "installed")
        print_status("MobSF Root CA installed successfully.");
      else if (json.message === "removed")
        print_status("MobSF Root CA removed successfully.");
      else
        print_status(json.message);
    });
    return false;  
}); 


//MobSF Global Proxy

$("#proxy").click(function() {
  var stext = $("#proxy").text();
  var act;
  if (stext.includes("Unset HTTP(S) Proxy")){
    $("#proxy").html("<i class='fas fa-eye'></i> Set HTTP(S) Proxy");
    act = "unset";
  } else {
    $("#proxy").html("<i class='fas fa-eye-slash'></i> Unset HTTP(S) Proxy");
    act = "set";
  }
  action(document.location.origin + '/global_proxy/', {action: act}, function(json) {
      if (json.message === "set")
        print_status("MobSF Global HTTP(S) interception proxy is applied.");
      else if (json.message === "unset")
        print_status("MobSF Global HTTP(S) interception proxy is removed.");
      else
        print_status(json.message);
    });
    return false;  
});

function start_activity(activity){
  action('{% url "start_activity" %}', {hash: '{{ hash }}', 'activity': activity}, function(json) {
    if (json.status === "ok")
        print_status("Activity Started");
    else
      print_status(json.message);
  });
}

function start_deeplink(url){
  action('{% url "start_deeplink" %}', {hash: '{{ hash }}', 'url': url}, function(json) {
    if (json.status === "ok")
      print_status("Deeplink Triggered");
    else
      print_status(json.message);
  });
}

function activity_tester(test){
  action(document.location.origin + '/activity_tester/', {hash: '{{ hash }}', 'test': test}, function(json) {
    if (json.status === "ok")
      if (test === 'exported')
        print_status("Exported Activity testing completed.");
      else
        print_status("Activity testing completed.");
    else
      print_status(json.message);
  });
}
//Start ExportedActivity Tester
$("#expactt").click(function()  {
  print_status("Starting Exported Activity tester...")
  activity_tester('exported')
  return false;  
});

//Start Activity Tester
$("#actt").click(function()  {
  print_status("Starting Activity tester...")
  activity_tester('all_activities')
  return false;  
});

//SSL/TLS Tester
$('#run_tls_tests').click(function()  {
  const msg = "TLS/SSL tests will take 75 seconds to complete. While the application is running, please navigate through different activity flows/business logic.";
  $('#tls_1').text('-');$('#tls_2').text('-');$('#tls_3').text('-');$('#tls_4').text('-');
  print_status("Running TLS/SSL Security Tester");
  print_tls_progress("Running TLS Misconfiguration test.")
  print_tls_progress("Running TLS Pinning/Certificate Transparency test.")
  print_tls_progress("Running TLS Pinning/Certificate Transparency Bypass test.")
  print_tls_progress(msg)
  dynamic_loader();
  action(document.location.origin + '/tls_tests/', {hash: '{{ hash }}'}, function(json) {
    if (json.status === "ok"){
      stop_loader();
      // print_tls_progress(JSON.stringify(json.tls_tests))
      if (json.tls_tests.tls_misconfigured === true)
          $('#tls_1').text('❌')
      else
          $('#tls_1').text('✅')
      if (json.tls_tests.no_tls_pin_or_transparency === true)
          $('#tls_2').text('❌')
      else
          $('#tls_2').text('✅')
      if (json.tls_tests.pin_or_transparency_bypassed === true)
          $('#tls_3').text('❌')
      else
          $('#tls_3').text('✅')
      if (json.tls_tests.has_cleartext === true)
          $('#tls_4').text('❌')
      else
          $('#tls_4').text('✅')
      const ok = "TLS/SSL Security tests completed.";
      print_status(ok)
      print_tls_progress(ok)
    } else {
      stop_loader();
      print_status("TLS/SSL Security tests failed.")
      print_tls_progress("TLS/SSL Security tests failed.")
      print_tls_progress("[ERROR]")
      print_tls_progress(json.message)
    }
  });
  return false;  
}); 

// Run APK for Xposed
$("#run_app").click(function() {
    print_status("Launching App");
    action(document.location.origin + '/run_apk/', {hash: '{{ hash }}'}, function(json) {
      if (json.status==="ok"){
          print_status("Application launched.");
      } else {
          print_status("Failed to launch the application.");
      }
    });
    return false;  
});

// Logcat Stream
$("#logstream").click(function() {
    print_status("Logcat Steaming started.");
    setTimeout(function(){ window.open(document.location.origin + '/logcat/?package={{ package }}', '_blank');}, 500);   
    return false;  
}); 


// Load Frida Scripts
$("#loadscript").click(function() {
   var scripts = $('#fd_scs').val();
   action('{% url 'get_script' %}', {scripts: scripts, device: 'android'}, function(json) {
    if (json.status==="ok"){
        editor.getDoc().setValue(json.content);
    }
  });
  return false;  
});

// Frida Spawn, Session and Ps
function frida_instrument(frida_action, pid=null, new_pkg=null){
    // Save Frida Code to Session Storage
    var code = editor.getDoc().getValue();
    window.sessionStorage.setItem('code_android', code);
    // Show Frida logs
    document.getElementById('frida-logs').style.display = 'block';
    // Show Frida inject button
    document.getElementById('frida_get').hidden = false;
     var default_hooks = [];

    $.each($("input[name='default_hooks']:checked"), function(){            
        default_hooks.push($(this).val());
    });
    if(default_hooks.includes("api_monitor"))
      $('#apimon').show();
    else
      $('#apimon').hide();
    var auxiliary_hooks = [];
    $.each($("input[name='auxiliary']:checked"), function(){            
        auxiliary_hooks.push($(this).val());
    });

    if (frida_action === 'spawn'){
      document.getElementById('frida_session').disabled = false;
      print_status("Instrumenting the application with Frida.");
    } else if (frida_action === 'session' && pid === null){
      print_status("Injecting Frida script to existing session.");
    } else if (pid){
      print_status("Attaching to PID: " + parseInt(pid));
    } else if (frida_action == 'ps'){
      print_status("Enumerating running processes.");
    } else if (frida_action == 'get'){
      print_status("Getting injected frida script.");
    }
    action('{% url 'android_instrument' %}', {
      frida_action,
      pid, // attach pid
      new_package: new_pkg, // attach package
      hash: '{{ hash }}',
      default_hooks: default_hooks.join(","),
      auxiliary_hooks: auxiliary_hooks.join(","),
      class_name: $('#class_name').val(),
      class_search:  $('#class_search').val(),
      class_trace:  $('#class_trace').val(),
      frida_code: editor.getDoc().getValue(),
    }, function(json) {
      if (json.status !== "ok")
        print_status(json.message);
      // Attach to a running process
      if (frida_action == 'ps' && json.message && json.message.length > 0 && Array.isArray(json.message)){
        $("#process_select").empty();
        json.message.forEach(function(p) {
          $('<option>').val(p.pid.toString() + ',' + p.identifier.toString()).text(p.pid.toString() + ': ' + p.name.toString() + ' - ' + p.identifier.toString()).appendTo('#process_select');
        });
        $('#frida_attach_mdl').modal('toggle');
      } else if (frida_action =='get'){
        var injected = document.getElementById("injected_content");
        injected.innerHTML = '<pre id="injected-pre"></pre>';
        document.getElementById("injected-pre").textContent = json.message;
        EnlighterJS.enlight( document.getElementById('injected-pre'), {
          theme: 'enlighter',
          linehover: false,
          textOverflow: 'scroll',
          language: 'javascript',
        });
        $('#get_code_modal').modal('toggle');
      }
  });
}

// Frida Spawn
$("#frida_spawn").click(function() {
  frida_instrument('spawn');
  return false;  
}); 

// Frida Session
$("#frida_session").click(function() {
  var default_hooks = "input[name='default_hooks']";
  if ($(default_hooks + ":checked").length == $(default_hooks).length)
      // If all default hooks are selected, uncheck all during injection
      $(default_hooks + ':checkbox').prop("checked", false );
  frida_instrument('session');
  return false;  
}); 


// Frida Get Processes to attach
$("#frida_attach").click(function() {
  frida_instrument('ps');
  return false;  
}); 

// Frida Attach to Pid
$("#attach_to_pid").click(function() {
  var values = $('#process_select').val();
  var pid = values.split(',')[0];
  var package = values.split(',')[1];
  frida_instrument('session', pid, package);
  $('#frida_attach_mdl').modal('hide');
  return false;  
}); 

// Frida Get Injected Script
$("#frida_get").click(function() {
  frida_instrument('get');
  return false;  
});

//Frida Get Runtime Dependencies
$("#deps").click(function() {
    print_status("Getting application runtime dependencies.");
    action(document.location.origin + '/get_dependencies/', {hash: '{{ hash }}'}, function(json) {
      if (json.status==="ok"){
          print_status("Dependencies collected!");
      } else {
          print_status(json.message);
      }
    });
    return false;  
});

//Dump App data
function dump(){
  action(document.location.origin + '/download_data/', { hash: '{{ hash }}'}, function(json) {
    if (json.status==="ok"){
      print_status("Application data dumped!");
      print_status("Generating Report...Please Wait!");
      //Call reporting
      window.location = document.location.origin+"/dynamic_report/{{ hash }}";
    } else {
      print_status(json.message);
    }
  });
}
  
//Finish & Generate Report
$("#stop").one( "click", function() {
  print_status("Collecting data...");
  //Stop Screen Casting if it's running
  var stext = $("#screen").text();
  if (stext.includes("Stop Screen"))
    $("#screen").click();
  action(document.location.origin + '/collect_logs/', { hash: '{{ hash }}'}, function(json) {
    if (json.status==="ok"){
      $('#stop').addClass("btn btn-success");
      $('#stop').text("Please Wait...");
      print_status("Downloading logs.");
      print_status("Stopping Application.");
    } else{
      print_status('Failed to collect data.')
      print_status(json.message)
    }
    dump();
  });
  return false;  
});

//end document.ready
});
</script>
{% endblock %}
