mantua (named after 8th circle of hell), is AntiDebug, AntiVM, AntiAV C library for linux.
This project is for malware analysts and for creator of CTF or cyber security exercises.
This project can be also used for your proprietary software to protect your Intellectual Property.
Install libelf-dev for binary editing we use in storage rewrite
sudo apt install libelf-dev
./test/test.c - is mine test file which is used in Makefile to test all functionality. If you use AUTO_TIME capsules, at your first start you have to use linker from user-space because if its served trough kernel you will get locking which prevent our binary rewrite, in my case:
sudo /lib64/ld-linux-x86-64.so.2 ./build/test
For finding right path use
ldd ./build/test
....
....
/lib64/ld-linux-x86-64.so.2 (0x00007f30ffcff000)
....
For all other runs you run it just by:
sudo ./build/test
- sudo if block_tracing() is used
./bypasses/ directory contain some bypasses for mantua functionality, if its not possible anymore, it contain _FIXED in name
Macro which contain rewrite of bytes from symbol _init with 0x90. This functionality is triggered if we dont have error_handler function pointer defined. If we have error_handler, its called instead. To define error_handler just give him defined function like:
void error()
{
// Custom code instead of bytes rewrite
}
int main()
{
...
error_handler = error;
...
}
Function which initialize mantua library, change permissions of some addresses (for BREAK_EVERYTHING functionality), and read persistent time storage if we have one.
Function which at first run save AUTO_TIME time capsules into separate section and rewrite storing function. If you are using AUTO_TIME functionality call this function before your infinity loops, if any are used. Argument is argv[0] (program path and name)
For now, this library have 4 antidebug functionality.
This functionality basically read it self from memory which means if the default value is different then value at runtime, your code have INT3 which is software breakpoint. Be careful, this function counts 0xcc which can be part of valid instruction so return is not zero every time (we can find this via objdump -d | grep " cc"), but in runtime it have still the same value if software breakpoints are not inserted
Return value is number of 0xcc found from symbol _start to symbol __etext
Program read /proc/self/status and check if TracerPid is 0, if not we call BREAK_EVERYTHING(). If you want to you use this functionality you have to run this function before block_tracing()
return 0 if not traced, 1 if is.
We fork and trace our child, and child start tracing us, if this all takes more than second, we BREAK_EVERYTHING(). If the child is not created and we don't receive 1 from pipe within one second we also BREAK_EVERYTHING(). For this functionality we have to run our program with root privileges
we return 0 if forking and tracing was successfull, -1 if not
Time capsules are control time between instructions. You can define this time, or it can be defined automatically. With this you can prevent breakpointing in your code, because breakpoints will increase execution time.
Example of time capsule:
int cap1 = start_time_capsule(1500);
printf("Im in capsule\n");
if (stop_time_capsule(cap1) < 0)
printf("Capsule 1 taken Longer than 1500 microseconds\n");
or for automatic time:
int autocap1 = start_time_capsule(AUTO_TIME);
printf("Im in AUTO_TIME capsule \n");
if (stop_time_capsule(autocap1) < 0)
printf("AUTO_TIME capsule taken longer\n");
Starting capsule, argument is max time for capsule. In case of automatic time use macro AUTO_TIME. Function return ID of capsule.
Stopping capsule, argument is ID of capsule and return is 0 if time was under defined time, or -1 if your block of code taken longer
Program read /proc/cpuinfo and check if any line contain string hypervisor. If contain we call BREAK_EVERYTHING().
return 1 if we found the string, 0 if not
Reads kernel log and check if any of needles exists in haystack, if we contain we call BREAK_EVERYTHING().
return 1 if we found needle in haystack, 0 if not
Program encrypt your written function with aes and rewrite original in binary**, for now it does not work with auto time capsules.
Set your function to crypter
Start crypter with his rewrite functionality