Last week, security researcher Tal Liberman published an article concerning a new malicious attack technique of using Windows functions to insert shellcode into memory. Known as “AtomBombing”, this technique takes advantage of existing Windows functions, then attempts a stack pivot with a known bypass technique called Return-Orientated-Programming (ROP) chaining to gain code execution within the context of another process.
“AtomBombing” takes advantage of existing Windows functions to write shellcode to an area of memory accessible to other processes referred to as Windows atom tables and then execute that shellcode using known techniques to bypass Date Execution Prevention (DEP). However, a number of steps have to occur in order for the malicious code to execute; interrupting any of them will cause the attack to fail.
1. Malicious shellcode is written into non-executable memory with the 'GlobalAddAtom' function. The Windows Atom Tables are usually used to store strings for easy access by running threads. More information about Atom Tables can be found here. Content can be retrieved from this table with the 'GlobalGetAtomName' function.
2. Though the shellcode now exists in memory as part of the global atom table, a remote process must be made to read the specific atom into its own memory space. This is achieved by abusing ‘NtQueueApcThread’, an undocumented syscall normally called from ‘QueueUserApc’, to invoke ‘GlobalGetAtomName’ in threads that are amenable to this procedure call. Although abused and probably a strong indicator of malicious intent, the API call is made in a way that will not cause any alarm in modern memory defenses. This is where the primary novelty of Liberman’s attack resides.
3. After a process is made to invoke GlobalGetAtomName with the arguments of the attacker’s choosing, the shellcode must be made to execute. Liberman uses a known method of bypassing DEP called Return-Oriented-Programming (ROP) chaining to do so. The ROP chain technique Liberman employs has three steps of its own:
a. Allocate memory where the shellcode can be executed. We need a region of memory that is not protected by DEP.
b. Copy shellcode from the Atom Table to this new unprotected space.
c. Execute the shellcode.
4. Before the ROP chain exploit can execute, it must first seize control flow from a running thread. Liberman employs a stack pivot to do so:
mov eax, edi;
add ax, 0xc4;
mov esp, [eax]; //This is the stack pivot
sub sp, 0x1024; // This is needed for alignment purposes
The “move esp, [eax]” instruction above hijacks the regular flow of process execution to point to the ROP chain that Liberman has crafted.
NOTE: Though the use of the Windows Atom Table was clever, bypassing DEP with ROP chaining has been around since at least 2007.
CylancePROTECT with Memory Defense enabled detects this action as a “Stack Pivot” exploitation attempt. Though this technique is capable of bypassing the memory protection features of many security solutions, CylancePROTECT stops the execution of the malicious shellcode before it ever executes.
Shacham, H. (October 2007). "The geometry of innocent flesh on the bone: return-into-libc without function calls (on the x86)". Proceedings of the 14th ACM conference on Computer and communications security - CCS '07. pp. 552–561. doi:10.1145/1315245.1315313. ISBN 978-1-59593-703-2.