Runtime application self-protection is a way to help prevent malware from being executed on a system – it’s also known as “self-protecting code”. This post outlines the basic principles of runtime application self-protection and includes a step-by-step walkthrough on adding runtime application self-protection to your project. It also goes into more detail about some of the risks you might want to mitigate with this technique.
Background
It uses an anti-execution technology called ASLR (Address Space Layout Randomization). It is essentially a form of memory randomization that puts all executable memory addresses into a different location in the memory map. This prevents a program from executing the same code addresses repeatedly because they’ll always be different each time. This can help to reduce the odds of malware being resistant to dynamic analysis techniques, such as automatic instrumentation (e.g. static code analysis).
Runtime application self-protection (RASP) is a technique that uses an anti-execution technology called ASLR (Address Space Layout Randomization), which is essentially a form of memory randomization that puts all executable memory addresses into a different location in the memory map.
This prevents a program from executing the same code addresses repeatedly because they’ll always be different each time. This can help to reduce the odds of malware being resistant to dynamic analysis techniques, such as automatic instrumentation (e.g. static code analysis).
The downside to ASLR is that it’s entirely software-based. So malware can detect its use by looking for specific memory addresses or other anti-malware behavior.
What is Runtime Application Self Protection?
Runtime application self-protection is a technique that uses hardware randomisation rather than software randomisation (i.e. ASLR) to make executable memory addresses unable to be predicted and detected by malware.
The technique is grounded in the concept of writing code that can be executed multiple times – because it can be executed numerous times. It makes sense to protect it from being repeatedly run by preventing its execution at the software level.
A benefit of this technique is that because the executable memory addresses are randomised, a malicious program cannot predict where they are located and could therefore not find them when searching for them with a debugger. This makes malware analysis using a debugger virtually impossible, which seems like a beneficial property. ASLR also has this weakness – as mentioned earlier, programs don’t see their executable memory locations as randomised; they have to be told what their background is specifically. RASP doesn’t need to say to the program where its executable memory addresses are located because it uses hardware randomisation to do this automatically.
The downside of this technique is that any gap in the amount of executable memory in your project should also be considered a weakness. Because ASLR relies on software to randomise executable memory addresses, malware can detect its presence simply by looking for all possible locations for its execution. If you have only 50 bytes of executable memory (RAM), you’re in a pretty weak position if malware can predict that there could be 18 different locations that you could execute at least one instruction from because those 18 different places would be all different from each other.
A less ideal situation would involve an application with so much executable memory that it can handle many thousands of instructions being executed at once. In this case, a malicious program may be able to predict where all of your application’s instructions could be found if they’re placed in the correct memory locations. But most malware won’t want to bother with high code density programs like these, so in all likelihood, the amount of executable memory you have is not particularly problematic.
Self-Protection Measures
The reason there’s no good solution to the above scenario is that any gap in executable memory will always come back to innocent users, who may then install or execute a malicious program.
The solution to this problem is to put two types of self-protection measures in place: First, we can randomize the memory space through hardware so that malware can’t detect it.
And second, we can make the executable memory inaccessible. The reason there’s no good solution to the above scenario is that any gap in executable memory will always come back to innocent users, who may then install or execute a malicious program.
The solution to this problem is to put two types of self-protection measures in place: First, we can randomize the memory space through hardware so that malware can’t detect it. And second, we can make the executable memory inaccessible.
The idea is to make it so that a malicious program would have to know the address of our application’s executable memory to attempt to target it. Therefore, the protection against malware isn’t that we randomise our executable memory addresses so that malware can’t find them when searching for them, but rather that we obscure the location of our executable memory from malware (and from ourselves) entirely.
Programming with RASP
If you’re working with an application development language like C/C++, for example, then you will be able to implement RASP at runtime as a way of protecting your application. Simply put, you can change the virtual address space of your application and prevent it from being mapped into memory should a user try to run it with a debugger. Instead of mapping the memory space under /proc/sys/kernel/randomize_va_space, you could configure your OS to map one or more other virtual addresses with no corresponding physical locations.
If you’re working with an application development language like C/C++, for example, then you will be able to implement RASP at runtime as a way of protecting your application. Simply put, you can change the virtual address space of your application and prevent it from being mapped into memory should a user try to run it with a debugger. Appsealing will provide you with the best deal.
You can manually make the changes to the OS and get them working now. But, because these changes are made at runtime, malware can adjust its behaviour and look for these memory spaces. Memory space is never truly secure, as its contents will almost always reveal some helpful information (e.g. stack traces) that you wouldn’t want your malware to be able to see.