What is rwx memory?
Allocate memory with RWX (read, write, and execute) permissions to write shellcode into, and execute it. My gut feeling is that this probably isn't a problem. What both techniques have in common is that they still need to allocate and protect memory (RW -> RX or RWX). Note: this answer corresponds to the original question. A tool that detects memory pages with vulnerable protection - nkakuev/rwx- checker.
Hello, cybersecurity enthusiasts and white hackers!
This is a result of my own research on another process injection technique.
Let’s take a look at logic of our classic code injection malware:
As you remember, we use VirtualAllocEx which is allows to us to allocate memory buffer for remote process, then, WriteProcessMemory allows you to copy data between processes. And CreateRemoteThread you can specify which process should start the new thread.
What about another way? it is possible to enumerate currently running target processes on the compromised system - search through their allocated memory blocks and check if any those are protected with RWX, so we can attempt to write/read/execute them, which may help to evasion some AV/EDR.
The flow is this technique is simple, let’s go to investigate its logic:
Loop through all the processes on the system:
Loop through all allocated memory blocks in each process:
Then, we check for memory block that is protected with RWX:
if ok, print our memory block (* for demonstration *):
write our payload to this memory block:
then start a new remote thread:
Full C++ source code of our malware is:
As usually, for simplicity I used meow-meow messagebox payload:
Let’s go to see everything in action. Compile our practical example:
Then run it! In our case victim machine is Windows 10 x64:
As you can see, everything is worked perfectly! :)
Let’s go to check one of our victim process, for example OneDrive:
Then, upload our malware to VirusTotal:
https://www.virustotal.com/gui/file/5835847d11b7f891e70681e2ec3a1e22013fa3ffe31a36429e7814a3be40bd97/detection
So, 7 of 69 AV engines detect our file as malicious.
Moneta64.exe result:
The reason why it’s good to have this technique in your arsenal is because it does not require you to allocate new RWX memory to copy your payload over to by using VirtualAllocEx which is more popular and suspicious and which is more closely investigated by the blue teamers.
I hope this post spreads awareness to the blue teamers of this interesting technique, and adds a weapon to the red teamers arsenal.
VirtualQueryEx CreateToolhelp32Snapshot Process32First Process32Next OpenProcess Taking a snapshot and viewing processes WriteProcessMemory CreateRemoteThread Hunting memory Moneta64.exe source code in Github
W^X ("write xor execute", pronounced W xor X) is a security feature in operating systems and virtual machines. It is a memory protection policy whereby every page in a process's or kernel's address space may be either writable or executable, but not both. Without such protection, a program can write (as data "W") CPU instructions in an area of memory intended for data and then run (as executable "X"; or read-execute "RX") those instructions. This can be dangerous if the writer of the memory is malicious. W^X is the Unix-like terminology for a strict use of the general concept of executable space protection, controlled via the mprotect system call.
W^X is relatively simple on processors that support fine-grained page permissions, such as Sun's SPARC and SPARC64, AMD's AMD64, Hewlett-Packard's PA-RISC, HP's (originally Digital Equipment Corporation's) Alpha, and ARM.
The term W^X has also been applied to file system write/execute permissions to mitigate file write vulnerabilities (as with in memory) and attacker persistence. Enforcing restrictions on file permissions can also close gaps in W^X enforcement caused by memory mapped files. Outright forbidding the usage of arbitrary native code can also mitigate kernel and CPU vulnerabilities not exposed via the existing code on the computer. A less intrusive approach is to lock a file for the duration of any mapping into executable memory, which suffices to prevent post-inspection bypasses.
Some early Intel 64 processors lacked the NX bit required for W^X, but this appeared in later chips. On more limited processors such as the Intel i386, W^X requires using the CS code segment limit as a "line in the sand", a point in the address space above which execution is not permitted and data is located, and below which it is allowed and executable pages are placed. This scheme was used in Exec Shield.
Linker changes are generally required to separate data from code (such as trampolines that are needed for linker and library runtime functions). The switch allowing mixing is usually called execstack on Unix-like systems
W^X can also pose a minor problem for just-in-time compilation, which involves an interpreter generating machine code on the fly and then running it. The simple solution used by most, including Firefox, involves just making the page executable after the interpreter is done writing machine code, using VirtualProtect on Windows or mprotect on Unix-like operating systems. The other solution involves mapping the same region of memory to two pages, one with RW and the other with RX. There is no simple consensus on which solution is safer: supporters of the latter approach believe allowing a page that has ever been writable to be executed defeats the point of W^X (there exists an SELinux policy to control such operations called allow_execmod) and that address space layout randomization would make it safe to put both pages in the same process. Supporters of the former approach believe that the latter approach is only safe when the two pages are given to two separate processes, and inter-process communication would be costlier than calling mprotect.
W^X was first implemented in OpenBSD 3.3, released May 2003. In 2004, Microsoft introduced a similar feature called DEP (Data Execution Prevention) in Windows XP. Similar features are available for other operating systems, including the PaX and Exec Shield patches for Linux, and NetBSD's implementation of PaX. In Red Hat Enterprise Linux (and automatically CentOS) version 5, or by Linux Kernel 2.6.18-8, SELinux received the allow_execmem, allow_execheap, and allow_execmod policies that provide W^X when disabled.
Although W^X (or DEP) has only protected userland programs for most of its existence, in 2012 Microsoft extended it to the Windows kernel on the x86 and ARM architectures. In late 2014 and early 2015, W^X was added in the OpenBSD kernel on the AMD64 architecture. In early 2016, W^X was fully implemented on NetBSD's AMD64 kernel and partially on the i386 kernel.
macOS computers running on Apple silicon processors enforce W^X for all programs. Intel-based Macs enforce the policy only for programs that use the OS's Hardened Runtime mode.
Starting with Firefox 46 in 2016, Firefox's virtual machine for JavaScript also implements the W^X policy.
Starting with .NET 6.0 in 2021, .NET now uses W^X.
Process segment permissions may vary across architectures and implementations. For example, it is expected that on more recent x86 Linux systems that GCC creates binaries with non-executable stacks. In contrast with this, it used to be the case that MIPS did not even support an non-executable stack - in other words, every MIPS binary had its stack permissions set to RWE.
A kernel patch had to be developed in order to support MIPS executable stack protection:
Here is a concrete example, using a MIPS ELF binary from a ZTE router:
Note the permissions of segment GNU_STACK:
Injecting and executing shellcode from a local or target process requires memory where the shellcode could be written to, read from and executed.
Some shellcode injection techniques allocate PAGE_EXECUTE_READWRITE memory block, fill it with shellcode and create a thread pointing to that shellcode. It's not a very common thing for bening applications to do and this is something AV/EDR solutions may punish you for if they catch you doing it.
Some techniques allocate PAGE_READWRITE first, write shellcode to the allocated memory, protect it with PAGE_EXECUTE_READ and then execute it, which means that at no point in time there's an RWX memory block in the target process. It is a bit stealthier and may help one sneak past AVs/EDRs.
What both techniques have in common is that they still need to allocate and protect memory (RW -> RX or RWX). Having said that, it is possible to brute-force/enumerate currently running target processes on the compromised system - search through their allocated memory blocks and check if any those are protected with RWX, so we can attempt to write/read/execute them, which may help evade some optics.
In this lab I will write a simple program that will:
Running the Code with breakpoint set on line 31 will be hit if the conditions on line 27 are met. The conditions we are checking for are:
Once the breakpoint is hit, we can see that the memory region 27c727a0000 is RX protected, is private and commited and now contains our shellcode (starting with bytes fc 48 83 e4) :
If you noticed and were wondering...
Let's build the program and run it - we can see we got some meterpreter shells.
{% hint style="warning" %} The below provided code is a dirty POC and may crash certain processes and the Visual Studio banner appearing in the above GIF proves it - the shellcode got injected into Visual Studio (devenv.exe) that crashed and restarted itself. {% endhint %}
{% tabs %} {% tab title="rwx-hunter.cpp" %}
{% endtab %} {% endtabs %}
Related Questions
No More Questions available at this moment!